openapi: 3.0.2
info:
  license:
    url: https://try.be
    name: MIT
  version: 1.0.0
  title: Trybe API
  x-logo:
    url: /images/logo.svg
    altText: Trybe
  description: |
    The Trybe REST API powers everything the product does — availability search,
    bookings, customer profiles, memberships, vouchers, inventory, payments and
    integrations. All resources are JSON and authenticated with a Bearer token.

    The full spec is OpenAPI 3.1.0. See the [getting started guide](/guides/getting-started)
    for a five-minute walkthrough of your first request.
  contact:
    name: Trybe API support
    email: tech-support@try.be
    url: https://try.be
servers:
  - url: https://api.try.be
    description: Production — live data, real payments and notifications.
  - url: https://api.playground.try.be
    description: Playground — test mode payments, whitelist-only emails. Safe to break.
security:
  - bearerAuth: []
tags:
  - name: Admin
    description: |
      Endpoints for managing the Trybe platform
  - name: AdyenIntegration
    description: Manage a site's own integration with Adyen.
  - name: AppointmentEnquiries
    description: Manage appointment enquiries.
  - name: AppointmentTypes
    description: |
      An `AppointmentType` is the catalog record for a bookable
      appointment — what it's called, how long it runs, which
      practitioners can deliver it, the rooms and equipment it
      consumes, its pricing, deposit and cancellation policy, and the
      categories it appears in on the booking storefront. Appointment
      types are the source the booking flow reads from when listing
      offerings and computing slot availability; the resulting
      booking is an [Appointment](/endpoints/Appointments).
    x-info:
      baseSchema:
        title: AppointmentType
        description: An `AppointmentType` offering model.
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
          allocate_multi_capacity_rooms:
            type: boolean
          canada_rmt_eligible:
            type: boolean
          categories:
            type: array
            items:
              $ref: '#/components/schemas/schemas_Category'
          category_ids:
            type: array
            items:
              type: string
              format: object-id
          contraindications:
            type: array
            items:
              $ref: '#/components/schemas/Contraindication'
          cross_sell_offerings:
            type: array
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          currency:
            $ref: '#/components/schemas/properties_currency'
          customer_cancellation_min_duration:
            type: string
            nullable: true
            example: P7D
          customer_cancellation_permitted:
            $ref: '#/components/schemas/customerCancellationPermitted'
          customer_reschedule_min_duration:
            type: string
            nullable: true
            example: P7D
          customer_reschedule_permitted:
            $ref: '#/components/schemas/customerReschedulePermitted'
          customers_only:
            type: boolean
          description:
            type: string
          durations:
            type: array
            items:
              type: integer
          end_buffer:
            type: integer
            nullable: true
          enquiries_enabled:
            type: boolean
          external_id:
            type: string
            nullable: true
            description: An external identifier for this offering.
          equipment_ids:
            type: array
            items:
              type: string
              format: object-id
          image:
            $ref: '#/components/schemas/Media'
            nullable: true
          include_pricing_on_calendar:
            type: boolean
          max_advance_bookings_interval:
            type: string
            nullable: true
          max_guests:
            type: integer
          practitioners_per_guest:
            type: integer
            description: The number of practitioners that are required for each guest to be booked for this appointment type
          max_per_basket:
            type: integer
            nullable: true
          max_per_guest:
            type: integer
            nullable: true
          members_only:
            type: boolean
          membership_booking_windows:
            type: array
            items:
              $ref: '#/components/schemas/MembershipBookingWindow'
          membership_booking_windows_enabled:
            type: boolean
          meta:
            title: AppointmentTypeMeta
            type: object
            additionalProperties: false
            properties:
              description:
                type: string
                nullable: true
              title:
                type: string
                nullable: true
            required:
              - description
              - title
          min_advance_bookings_interval:
            type: string
            nullable: true
          min_guests:
            type: integer
          name:
            type: string
          offered_online:
            type: boolean
          permitted_membership_type_ids:
            type: array
            items:
              type: string
              format: object-id
          private:
            type: boolean
          product_code:
            type: string
            nullable: true
          practitioner_ids:
            type: array
            items:
              type: string
              format: object-id
          price_rules:
            type: array
            items:
              $ref: '#/components/schemas/PriceRule'
          related_retail_offerings:
            type: array
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          revenue_centre:
            type: string
            nullable: true
          room_ids:
            type: array
            items:
              type: string
              format: object-id
          shop_practitioner_selection:
            type: string
            nullable: true
            enum:
              - by_name
              - by_gender
          site_ids:
            type: array
            items:
              type: string
              format: object-id
          yield_management:
            $ref: '#/components/schemas/YieldManagement'
          standard_price:
            type: integer
            nullable: true
            description: |
              The standard price for this appointment type, in the smallest
              currency unit (e.g. pence). `null` if a standard price hasn't
              been configured — this is distinct from a price of zero.
            example: 5000
          start_time_interval:
            type: integer
          tag_ids:
            type: array
            items:
              type: string
              format: object-id
          tags:
            type: array
            items:
              $ref: '#/components/schemas/Tag'
          upsell_offerings:
            type: array
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          visibility:
            $ref: '#/components/schemas/visibility'
          deleted_at:
            $ref: '#/components/schemas/deletedAt'
          updated_at:
            $ref: '#/components/schemas/updatedAt'
        required:
          - id
          - allocate_multi_capacity_rooms
          - canada_rmt_eligible
          - categories
          - category_ids
          - contraindications
          - cross_sell_offerings
          - currency
          - customer_cancellation_min_duration
          - customer_cancellation_permitted
          - customer_reschedule_min_duration
          - customer_reschedule_permitted
          - customers_only
          - description
          - durations
          - end_buffer
          - enquiries_enabled
          - equipment_ids
          - external_id
          - include_pricing_on_calendar
          - max_advance_bookings_interval
          - max_guests
          - practitioners_per_guest
          - max_per_basket
          - max_per_guest
          - members_only
          - membership_booking_windows
          - membership_booking_windows_enabled
          - meta
          - min_advance_bookings_interval
          - min_guests
          - name
          - offered_online
          - practitioner_ids
          - price_rules
          - private
          - product_code
          - related_retail_offerings
          - revenue_centre
          - room_ids
          - shop_practitioner_selection
          - site_ids
          - standard_price
          - yield_management
          - start_time_interval
          - tag_ids
          - tags
          - visibility
          - upsell_offerings
          - deleted_at
          - updated_at
  - name: Appointments
    description: An `Appointment` represents a booking of an `AppointmentType`.
    x-info:
      baseSchema:
        title: Appointment
        type: object
        additionalProperties: false
        properties:
          id:
            description: The ID of the appointment.
            type: string
            format: object-id
          appointment_type_id:
            description: The ID of the appointment type.
            type: string
            format: object-id
          appointment_type_name:
            description: The name of the appointment type.
            type: string
            example: 60 minute massage
          currency:
            $ref: '#/components/schemas/properties_currency'
          customer_id:
            description: The ID of the customer this appointment is for.
            type: string
            format: object-id
          duration:
            description: The duration of the appointment in minutes.
            type: integer
            example: 60
          email:
            description: The email address of the customer.
            type: string
            example: janedoe@example.com
          end_buffer:
            description: The number of minutes blocked out at the end of the appointment for cleaning or changeover.
            type: integer
            example: 15
          end_time:
            description: The end time this appointment is for.
            type: string
            format: date-time
            example: '2019-01-15T13:00:00+01:00'
          first_name:
            description: The first name of the customer.
            type: string
            example: Jane
          full_name:
            description: The full name of the customer.
            type: string
            example: Jane Doe
          guests:
            type: array
            items:
              $ref: '#/components/schemas/Guest'
          has_notes:
            description: Whether the appointment belongs to an order that has notes.
            type: boolean
            example: true
          has_outstanding_balance:
            description: Whether the appointment belongs to an order that has an outstanding balance.
            type: boolean
            example: true
          has_special_requests:
            description: Whether the appointment belongs to an order that has special requests.
            type: boolean
            example: true
          is_group_booking:
            description: Whether the appointment belongs to an order that has multiple guests.
            type: boolean
            example: true
          is_hotel_room_booking:
            description: Whether the appointment belongs to an order that is associated with a hotel room.
            type: boolean
            example: true
          is_locked:
            description: Whether the appointment is locked and should not be moved.
            type: boolean
            example: true
          is_part_of_package:
            description: Whether the appointment was sold as part of a package
            type: boolean
            example: true
          last_name:
            description: The last name of the customer.
            type: string
            example: Doe
          net_total:
            description: The net total of the appointment.
            type: integer
            example: 4950
          order_id:
            description: The ID of the order associated with this appointment.
            type: string
            format: object-id
          order_is_locked:
            description: Whether the order is locked
            type: boolean
            example: false
          order_item_id:
            description: The ID of the order item associated with this appointment.
            type: string
            format: object-id
          order_labels:
            type: array
            items:
              $ref: '#/components/schemas/schemas_Label'
          order_locked_at:
            description: The date the order was locked at
            type: string
            format: date-time
            example: '2019-01-15T12:00:00+01:00'
          order_ref:
            description: The order reference associated with this appointment.
            type: string
            example: TRY00
          organisation_id:
            description: The ID of the organisation the appointment belongs to.
            type: string
            format: uuid
          package_product_code:
            description: The product code for the package.
            type: string
            example: MAS123
          phone:
            description: The customer's phone number.
            type: string
            example: '+447727123456'
          practitioner_ids:
            description: The IDs of the practitioners this appointment assigned to.
            type: array
            items:
              type: string
              format: object-id
          practitioners:
            type: array
            items:
              $ref: '#/components/schemas/PractitionerSummary'
          product_code:
            description: A custom product code for the product.
            type: string
            nullable: true
            example: MAS123
          room:
            $ref: '#/components/schemas/RoomSummary'
          room_id:
            description: The ID of the room this appointment assigned to.
            type: string
            format: object-id
          site_id:
            description: The ID of the site the appointment belongs to.
            type: string
            format: uuid
          stage:
            description: The current stage of the order the appointment belongs to.
            type: string
            enum:
              - arrived
              - checked_out
              - in_treatment
              - not_arrived
          start_time:
            description: The start time this appointment is for.
            type: string
            format: date-time
            example: '2019-01-15T12:00:00+01:00'
          status:
            description: The status of the appointment.
            type: string
            enum:
              - confirmed
              - in_progress
              - new
          submitted_at:
            description: The date and time the appointment was submitted.
            type: string
            format: date-time
            example: '2019-01-15T12:00:00+01:00'
          total_cost:
            description: The total cost of the appointment.
            type: integer
            example: 5000
          created_at:
            $ref: '#/components/schemas/createdAt'
          updated_at:
            $ref: '#/components/schemas/updatedAt'
        required:
          - id
          - appointment_type_id
          - appointment_type_name
          - customer_id
          - duration
          - email
          - end_buffer
          - end_time
          - first_name
          - guests
          - has_notes
          - has_outstanding_balance
          - has_special_requests
          - is_group_booking
          - is_part_of_package
          - last_name
          - net_total
          - order_id
          - order_is_locked
          - order_item_id
          - order_labels
          - order_ref
          - organisation_id
          - phone
          - practitioner_ids
          - practitioners
          - product_code
          - room
          - room_id
          - site_id
          - stage
          - start_time
          - status
          - submitted_at
          - total_cost
          - created_at
          - updated_at
  - name: AreaBookingTypes
    description: |
      An `AreaBookingType` represents a type of area that can be booked at a site.
  - name: AreaBookings
    description: |
      An `AreaBooking` is a confirmed reservation of one or more
      `BookableArea`s — for example a pool cabana, treatment pod, or
      poolside lounger — against a customer order. Area bookings are
      created via the basket pipeline when an `AreaBookingType` is
      added to a basket, and remain the source of truth for the
      reservation throughout its lifecycle.
    x-info:
      baseSchema:
        title: AreaBooking
        description: |
          A confirmed booking of one or more `BookableArea`s — for example a
          cabana, treatment pod, or pool deck — against a customer order.
          An `AreaBooking` is created by the basket pipeline when an
          `AreaBookingType` is added to a basket, and remains the source of
          truth for the reservation throughout its life-cycle.
        type: object
        additionalProperties: false
        properties:
          id:
            description: The ID of the area booking.
            type: string
            format: object-id
          area_booking_type_id:
            description: The ID of the `AreaBookingType` this booking is for.
            type: string
            format: object-id
          area_booking_type_name:
            description: |
              The name of the `AreaBookingType` at the time the booking was
              made. This is captured at booking time so the value remains
              stable even if the parent type is later renamed.
            type: string
            example: Pool Cabana
          order_id:
            description: The ID of the order this area booking belongs to.
            type: string
            format: object-id
          order_ref:
            description: The human-readable reference of the parent order.
            type: string
            example: TRY00
          order_item_id:
            description: The ID of the `OrderItem` this area booking represents.
            type: string
            format: object-id
          order_labels:
            type: array
            items:
              $ref: '#/components/schemas/schemas_Label'
          order_is_locked:
            description: Whether the parent order has been locked from further changes.
            type: boolean
            example: false
          order_locked_at:
            description: The date and time the parent order was locked, if it has been.
            type: string
            format: date-time
            nullable: true
          status:
            description: The current status of the area booking.
            type: string
            enum:
              - confirmed
              - in_progress
              - new
          stage:
            description: The check-in stage of the parent order.
            type: string
            nullable: true
            enum:
              - arrived
              - in_treatment
              - checked_out
              - not_arrived
          customer_id:
            description: The ID of the customer the booking is for.
            type: string
            format: object-id
          email:
            description: The customer's email address.
            type: string
            example: janedoe@example.com
          phone:
            description: The customer's phone number.
            type: string
            example: '+447727123456'
          first_name:
            description: The customer's first name.
            type: string
            example: Jane
          last_name:
            description: The customer's last name.
            type: string
            example: Doe
          area_ids:
            description: The IDs of the `BookableArea`s assigned to this booking.
            type: array
            items:
              type: string
              format: object-id
          areas:
            description: Summary records for each assigned `BookableArea`.
            type: array
            items:
              $ref: '#/components/schemas/BookableAreaSummary'
          guests:
            type: array
            items:
              $ref: '#/components/schemas/Guest'
          start_time:
            description: When the booking starts.
            type: string
            format: date-time
            example: '2019-01-15T12:00:00+01:00'
          end_time:
            description: When the booking ends.
            type: string
            format: date-time
            example: '2019-01-15T13:00:00+01:00'
          duration:
            description: The duration of the booking in minutes.
            type: integer
            example: 60
          end_buffer:
            description: Minutes blocked out after the booking for changeover or cleaning.
            type: integer
            example: 15
          is_group_booking:
            description: Whether the parent order has more than one guest.
            type: boolean
            example: false
          has_outstanding_balance:
            description: Whether the parent order still has unpaid balance.
            type: boolean
            example: false
          has_notes:
            description: Whether the parent order has any notes.
            type: boolean
            example: false
          has_special_requests:
            description: Whether the parent order has special requests recorded.
            type: boolean
            example: false
          product_code:
            description: A custom product code for the `AreaBookingType`.
            type: string
            example: SPA-CABANA
          is_part_of_package:
            description: Whether this booking was sold as part of a `Package`.
            type: boolean
            example: false
          package_product_code:
            description: The product code of the parent `Package`, if any.
            type: string
          organisation_id:
            description: The ID of the organisation the booking belongs to.
            type: string
            format: uuid
          site_id:
            description: The ID of the site the booking belongs to.
            type: string
            format: uuid
          created_at:
            $ref: '#/components/schemas/createdAt'
          updated_at:
            $ref: '#/components/schemas/updatedAt'
        required:
          - id
          - area_booking_type_id
          - area_booking_type_name
          - order_id
          - order_ref
          - order_item_id
          - order_labels
          - order_is_locked
          - status
          - customer_id
          - email
          - phone
          - first_name
          - last_name
          - area_ids
          - areas
          - guests
          - start_time
          - end_time
          - duration
          - end_buffer
          - is_group_booking
          - has_outstanding_balance
          - has_notes
          - has_special_requests
          - product_code
          - is_part_of_package
          - organisation_id
          - site_id
          - created_at
          - updated_at
  - name: AuditLogs
    description: |
      Endpoints for viewing audit logs
  - name: Availability
    description: Retrieve availability for an offering.
  - name: AvvioIntegration
    description: |
      Manage a site's integration with Avvio, a hotel booking engine that
      powers overnight availability and pricing for the site.
  - name: Baskets
    description: |
      A `Basket` is the mutable, in-progress cart that a customer (or
      an integration acting on their behalf) builds before checkout —
      items, guests, discounts, payment methods and the paying
      customer all attach here. Totals on the basket are tentative;
      no money has moved.

      Submitting (`actionSubmitBasket`) runs the booking-engine
      validation suite — availability, reservation policies,
      practitioner / room / area constraints, deposits, intake-form
      requirements — and only on success creates the `Order`,
      reserves the bookings, and captures payment. Use Baskets for
      any customer-driven purchase.

      Post-submit reads and edits (refunds, cancellations, additional
      payments) go through [Orders](/endpoints/Orders). See
      [Basket vs Order](/guides/basket-and-checkout#basket-vs-order--whats-the-difference)
      in the basket-and-checkout guide for the full contrast.
    x-info:
      baseSchema:
        title: Basket
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
          applied_promo_code:
            $ref: '#/components/schemas/AppliedPromoCode'
          applied_promo_code_discount_total:
            type: integer
          applied_promo_code_id:
            type: string
            nullable: true
          coupon_codes:
            type: array
            items:
              $ref: '#/components/schemas/BasketCouponSummary'
          currency:
            $ref: '#/components/schemas/properties_currency'
          customer_id:
            type: string
            format: uuid
          discount_total:
            type: integer
          email:
            type: string
          guests:
            type: array
            items:
              $ref: '#/components/schemas/Guest'
          first_name:
            type: string
          is_promo_code_discount_applied:
            type: boolean
          items:
            type: array
            items:
              $ref: '#/components/schemas/Item'
          items_reserved_until:
            type: string
            format: date-time
            nullable: true
          last_name:
            type: string
          net_total:
            type: integer
          order_ref:
            type: string
            nullable: true
          organisation_id:
            type: string
            format: uuid
          outstanding_payment_amount:
            type: integer
          payments:
            type: array
            items:
              $ref: '#/components/schemas/Payment'
          phone:
            type: string
          promo_code_applied_at:
            type: string
            format: date-time
          promo_code_applied_by:
            $ref: '#/components/schemas/UserSummary'
          site_id:
            type: string
            format: uuid
          special_requests:
            type: string
            nullable: true
          status:
            description: The status of the `Basket`.
            $ref: '#/components/schemas/Status'
          submit_auth_amount:
            type: integer
            nullable: true
          submit_errors:
            type: array
            items:
              title: BasketSubmitError
              type: object
              additionalProperties: false
              properties:
                error:
                  type: string
                message:
                  type: string
                time:
                  type: integer
              required:
                - error
                - message
                - time
          submit_payment_amount:
            type: integer
            nullable: true
          submitted_at:
            type: string
            format: date-time
            nullable: true
          total_cost:
            type: integer
          total_paid_or_authed:
            type: integer
          total_tax:
            type: integer
          totals:
            title: BasketTotals
            type: object
            additionalProperties: false
            properties:
              applied_vouchers:
                type: integer
              auth_required:
                type: integer
              discounts:
                type: integer
              gross_total:
                type: integer
              net_total:
                type: integer
              payment_required:
                type: integer
              tax:
                type: integer
            required:
              - applied_vouchers
              - auth_required
              - discounts
              - gross_total
              - net_total
              - payment_required
              - tax
          voucher_codes:
            type: array
            items:
              $ref: '#/components/schemas/VoucherSummary'
          created_at:
            $ref: '#/components/schemas/createdAt'
          updated_at:
            $ref: '#/components/schemas/updatedAt'
        required:
          - id
          - applied_promo_code_discount_total
          - applied_promo_code_id
          - coupon_codes
          - currency
          - customer_id
          - email
          - discount_total
          - first_name
          - guests
          - is_promo_code_discount_applied
          - items
          - items_reserved_until
          - last_name
          - net_total
          - order_ref
          - organisation_id
          - outstanding_payment_amount
          - payments
          - phone
          - site_id
          - special_requests
          - status
          - submit_auth_amount
          - submit_payment_amount
          - submitted_at
          - total_cost
          - total_paid_or_authed
          - total_tax
          - totals
          - voucher_codes
          - created_at
          - updated_at
  - name: BlockedTimePresets
    description: |
      A `BlockedTimePreset` captures the reusable metadata for a
      common kind of blocked time — for example "Lunch break"
      (30 min, "break"), "Treatment-room cleaning" (15 min,
      "cleaning"), or "Team meeting" (60 min, "meeting"). Operators
      pick a preset in the calendar UI to create a `BlockedTime` with
      the configured duration, type, label, and colour pre-filled.
  - name: BlockedTimes
    description: |
      A `BlockedTime` carves a window out of a practitioner's, room's,
      or bookable area's calendar so it cannot be booked. Use blocked
      times for breaks, cleaning slots, internal meetings, or any
      other reason an otherwise-available resource should be hidden
      from the booking flow. Blocked times can recur on chosen
      weekdays via the `recurrence` payload.
  - name: BookableAreas
    description: |
      A `BookableArea` is a physical area at a site (e.g. cabana, hot
      tub, treatment pod) that customers reserve via an
      `AreaBookingType`. Each area has a capacity and an availability
      schedule made up of `AvailabilityRule`s.
    x-info:
      baseSchema:
        title: BookableArea
        description: |
          A `BookableArea` is a physical area that can be booked by guests
          via an `AreaBookingType` (e.g. a hot tub, a cabana, a treatment
          pod). Bookable areas have a `capacity` (number of simultaneous
          bookings) and an availability schedule made up of one or more
          `AvailabilityRule`s.
        type: object
        additionalProperties: false
        required:
          - id
          - organisation_id
          - site_id
          - name
          - description
          - capacity
          - availability_rules
        properties:
          id:
            type: string
            format: object-id
            description: Unique identifier of the bookable area.
            example: 5dcb47800000000000000000
          organisation_id:
            type: string
            format: uuid
            description: ID of the organisation the bookable area belongs to.
            example: 0193b6e0-3b56-7000-9f50-9d3d5e2c1111
          site_id:
            type: string
            format: uuid
            description: |
              ID of the site the bookable area belongs to. A bookable area
              is scoped to exactly one site.
            example: 0193b6e0-3b56-7000-9f50-9d3d5e2c2222
          name:
            type: string
            description: Display name for the bookable area. Shown to staff and customers.
            example: Hot Tub 1
          description:
            type: string
            nullable: true
            description: Long-form description of the bookable area.
            example: |
              Private rooftop hot tub for up to four guests. 38°C, sunset
              views over the gardens.
          capacity:
            type: integer
            minimum: 1
            description: |
              Maximum number of simultaneous bookings. `1` means
              exclusive-use; values > 1 allow shared occupancy.
            example: 4
          availability_rules:
            type: array
            description: |
              The `AvailabilityRule`s currently configured on this area.
              These determine when the area is bookable. Manage them via
              the `/shop/bookable-areas/{bookableAreaId}/availability-rules`
              endpoints.
            items:
              $ref: '#/components/schemas/AvailabilityRule'
          zones:
            type: array
            description: |
              Hydrated `Zone` records this bookable area belongs to. Zones
              group areas in the floor plan for spatial constraints.
            items:
              $ref: '#/components/schemas/Zone'
  - name: BookingEngine
    description: |
      Provider-agnostic endpoints that expose rates, age categories and
      other metadata for whichever booking-engine integration is
      currently active on a `Site` (for example Avvio, Guestline, or
      Mews). Useful for building UIs that need to map upstream
      booking-engine data onto Trybe room reservation types.
  - name: Brands
    description: |
      A `Brand` represents a collection of Sites
    x-info:
      baseSchema:
        type: object
        title: Brand
        description: A `Brand` object
        additionalProperties: false
        properties:
          id:
            type: string
            description: The ID of the brand
            format: uuid
          name:
            type: string
            description: The name of the brand
            example: Palm Tree Resorts
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation that the brand belongs to
          organisation_name:
            type: string
            description: The name of the organisation that the brand belongs to
            example: Palm Tree Holdings Ltd.
  - name: CalendarEvents
    description: A `CalendarEvent` represents an offering occurrence.
  - name: CalendarNotes
    description: |
      A `CalendarNote` is a free-form, date-scoped annotation that
      surfaces on the operator calendar for a site (e.g. public
      holidays, marketing events, known understaffed shifts). Notes
      do not affect availability or block bookings.
  - name: Campaigns
    description: |
      A `Campaign` is a targeted email marketing message sent to the members of a
      `CustomerSegment`. Campaigns can be scheduled in advance and track when they
      were sent. Campaign contents (localised subject and body) and send records
      (per-recipient delivery tracking) are managed as sub-resources of a campaign.
    x-info:
      baseSchema:
        type: object
        title: Campaign
        additionalProperties: false
        description: An email marketing campaign sent to the members of a `CustomerSegment`. A campaign can be scheduled in advance and tracks when it was sent.
        properties:
          id:
            type: string
            format: uuid
            description: The unique identifier of the campaign.
          name:
            type: string
            description: The display name of the campaign.
            example: Summer Promotion 2024
          progress:
            type: number
            format: float
            description: |
              The send progress of the campaign as a percentage (0–100). Only populated
              when `status` is `in_progress`; `null` otherwise.
            nullable: true
            minimum: 0
            maximum: 100
            example: 42.5
          scheduled_at:
            type: string
            format: date-time
            description: The datetime at which this campaign is scheduled to be sent, or `null` if not yet scheduled.
            nullable: true
          segment:
            type: object
            title: CampaignSegmentSummary
            additionalProperties: false
            description: A summary of the `CustomerSegment` this campaign is targeting, or `null` if no segment has been assigned.
            nullable: true
            properties:
              id:
                type: string
                format: uuid
                description: The ID of the segment.
              name:
                type: string
                description: The display name of the segment.
                example: Premium Members
            required:
              - id
              - name
          sent_at:
            type: string
            format: date-time
            description: The datetime at which this campaign was sent, or `null` if it has not yet been sent.
            nullable: true
          site_id:
            type: string
            format: uuid
          status:
            type: string
            description: |
              The current send status of the campaign.
              - `unsent` — no send records exist yet.
              - `in_progress` — sends have been created but at least one has not yet been sent.
              - `sent` — all send records have been sent.
            enum:
              - unsent
              - in_progress
              - sent
            example: unsent
        required:
          - id
          - name
          - progress
          - scheduled_at
          - segment
          - sent_at
          - site_id
          - status
  - name: CheckIns
    description: |
      A `CheckIn` represents an instance of a customer arriving at a
      site. Check-ins are typically created when a customer scans an
      associated barcode, taps a wearable on a Gantner reader, or is
      checked in manually via the Trybe app.
    x-info:
      baseSchema:
        title: CheckIn
        type: object
        additionalProperties: false
        description: |
          A `CheckIn` represents an instance of a customer arriving at a site. Check-ins are typically created when a customer scans an associated barcode, taps a wearable on a Gantner reader, or is checked in manually via the Trybe app.
        properties:
          id:
            type: string
            description: The ID of this check-in
            example: 000000-000000-000000-000000
          customer:
            $ref: '#/components/schemas/CheckInCustomer'
          membership_id:
            type: string
            description: The membership ID associated with this check-in
            example: 000000-000000-000000-000000
          site_id:
            type: string
            description: The site ID where this check-in happened
            example: 000000-000000-000000-000000
          method:
            $ref: '#/components/schemas/CheckInMethod'
          source:
            type: string
            nullable: true
            description: |
              Where the check-in/out originated: `app` (staff app check-in
              button), `kiosk` (self-service kiosk), or `gantner` (Gantner
              access gate). Null for records created before source tracking
              existed.
            enum:
              - app
              - kiosk
              - gantner
              - null
            example: kiosk
          checked_in_at:
            type: string
            description: The datetime when this check-in happened
            format: date-time
            example: '2021-01-01T00:00:00.000Z'
            nullable: true
          checked_out_at:
            type: string
            description: The datetime when this check-out happened
            format: date-time
            example: '2021-01-01T00:00:00.000Z'
            nullable: true
        required:
          - id
          - customer
          - membership_id
          - site_id
          - method
          - source
          - checked_in_at
          - checked_out_at
  - name: CommissionPackages
    description: |
      A `CommissionPackage` defines the commission rates a practitioner earns. Each package can have
      multiple rates with individual thresholds, date ranges, and evaluation periods. A rate pays
      either a percentage of the item's value or a flat amount per item, and a package's `weekly`
      or `bi_weekly` evaluation period can be configured to start on any day of the week.
  - name: Contraindications
    description: |
      A `Contraindication` represents a health condition or factor that
      may make certain offerings (such as treatments) unsuitable for a
      guest. Contraindications are defined at the organisation level
      and can be attached to customers to record any conditions that
      apply to them.
  - name: CouponCodes
    description: Endpoints for retrieving coupon code information and statistics.
  - name: Coupons
    description: A `Coupon` represents a form of credit against a membership.
    x-info:
      baseSchema:
        title: Coupon
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: The ID of the coupon
          name:
            type: string
            description: The name of the coupon
            example: Test coupon
          description:
            type: string
            description: A string to describe the coupon
            example: This coupon is a test
          locale_strings:
            type: object
            nullable: true
            description: Translations of the coupon's name and description, keyed by locale code. Managed via the coupon locale strings endpoints.
            additionalProperties:
              $ref: '#/components/schemas/CouponLocaleStrings'
          offering_discounts:
            type: array
            description: An array of offering_discounts belonging to this coupon. Each offering_discount describes what offerings the coupon is valid for.
            items:
              $ref: '#/components/schemas/OfferingDiscount'
          currency:
            type: string
            description: The currency of any amounts to be applied.
            example: gbp
          valid_weekdays:
            type: array
            description: An array of weekdays which this coupon is available for use
            items:
              type: string
              description: A weekday, in English, lowercase, and not shortened
              example: monday
          invalid_date_set_ids:
            type: array
            description: An array of IDs of `DateSet`s describing when this coupon is _not_ valid. The DateSet must belong to the same organisation as the coupon.
            items:
              type: string
              format: object-id
              description: The ID of the date set
          default_validity_interval:
            type: string
            description: The default duration this coupon is valid for, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P1Y
          default_multi_use:
            type: boolean
            description: The default for whether a code created from this coupon may be used multiple times
            example: true
          for_lead_booker_only:
            type: boolean
            description: |
              If true, only the lead booker of an order will be able to use this coupon. If false, any guest on the order will be able to use the coupon, including non-members.
            example: true
          max_uses:
            type: integer
            nullable: true
            description: The maximum number of times this coupon can be used within the specified max uses period
            example: 2
          max_uses_period:
            type: string
            nullable: true
            enum:
              - P1D
              - P1W
              - P1M
              - P1Y
            description: |
              The time period for usage limits when max_uses is set.
              The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
              P1D = daily limit, P1W = weekly limit, P1M = monthly limit, P1Y = yearly limit
          redemption_type:
            type: string
            enum:
              - manual
              - programmatic
            description: The redemption type of the coupon.
            example: manual
          site_id:
            type: string
            format: uuid
            nullable: true
            description: The ID of the site this coupon belongs to.
          created_at:
            type: string
            format: date-time
            description: The time and date that the coupon was created.
            example: '2020-02-24T12:00:00+01:00'
          updated_at:
            type: string
            format: date-time
            description: The time and date that the coupon was last updated.
            example: '2020-02-24T12:00:00+01:00'
          deleted_at:
            type: string
            format: date-time
            description: The time and date that the coupon was soft-deleted.
            example: '2020-02-24T12:00:00+01:00'
            nullable: true
        required:
          - id
          - name
          - description
          - locale_strings
          - offering_discounts
          - currency
          - valid_weekdays
          - invalid_date_set_ids
          - default_validity_interval
          - default_multi_use
          - for_lead_booker_only
          - max_uses
          - max_uses_period
          - redemption_type
          - site_id
          - created_at
          - updated_at
          - deleted_at
  - name: CourseTypes
    description: A `CourseType` represents an offering type.
  - name: CustomerCredits
    description: |
      A `CustomerCredit` represents a coupon credit issued to a
      customer — either automatically as a recurring membership
      benefit or manually as a one-off (e.g. a goodwill gesture).
      Each credit references the underlying `Coupon` that defines
      what it entitles the customer to.
  - name: CustomerLabels
    description: |
      Endpoints for attaching and detaching `Label`s on individual
      `Customer`s. Labels themselves are managed via the `Labels`
      endpoints.
  - name: CustomerMarketingPreferences
    description: |
      Endpoints for managing a `Customer`'s opt-in/out state against
      each of their organisation's `MarketingPreference`s.
  - name: CustomerNotes
    description: |
      A `CustomerNote` is free-form text recorded against a
      `Customer` by a staff member, used for capturing context that
      should follow the customer across visits (e.g. dietary
      requirements, preferences, behavioural flags).
  - name: CustomerSegmentMembers
    description: |
      A `CustomerSegmentMember` is the association between a `Customer` and a
      `CustomerSegment`. It tracks whether the customer is currently subscribed to
      receive communications for that segment.
    x-info:
      baseSchema:
        type: object
        title: CustomerSegmentMember
        additionalProperties: false
        description: A customer who is a member of a `CustomerSegment`. Tracks subscription state for marketing communications.
        properties:
          id:
            type: string
            format: uuid
            description: The unique identifier of the segment membership record.
          segment_id:
            type: string
            format: uuid
            description: The ID of the segment this membership belongs to.
          unsubscribed_at:
            type: string
            format: date-time
            description: The datetime at which the customer unsubscribed from this segment's communications, or `null` if they are currently subscribed.
            nullable: true
          customer:
            $ref: '#/components/schemas/CustomerSummary'
        required:
          - id
          - segment_id
          - unsubscribed_at
          - customer
  - name: CustomerSegments
    description: |
      A `CustomerSegment` is a named group of customers within a site that can be
      targeted for marketing campaigns. Segments may have optional filters based on
      labels or memberships to drive automatic membership.
    x-info:
      baseSchema:
        type: object
        title: CustomerSegment
        additionalProperties: false
        description: A named group of customers within a site that can be targeted for marketing campaigns. Segments can be defined manually or filtered automatically by label and membership criteria.
        properties:
          id:
            type: string
            format: uuid
            description: The unique identifier of the customer segment.
          name:
            type: string
            description: The display name of the segment.
            example: Premium Members
          site_id:
            type: string
            format: uuid
            description: The ID of the site this segment belongs to.
          filters:
            type: object
            title: CustomerSegmentFilters
            description: Optional filters that define automatic membership criteria for this segment. `null` indicates no filters are applied.
            nullable: true
            additionalProperties: false
            properties:
              all_customers:
                type: boolean
                description: When `true`, all customers in the site are included in the segment regardless of other filters.
              label_ids:
                type: array
                description: Customers that have all of the given label IDs are included in the segment.
                nullable: true
                items:
                  type: string
                  format: uuid
                  description: The ID of a label.
              membership_type_ids:
                description: Customers that hold a membership matching one of the given IDs are included in the segment. Use `true` to include customers with any active membership.
                oneOf:
                  - type: array
                    nullable: true
                    items:
                      type: string
                      format: uuid
                      description: The ID of a membership.
                  - type: boolean
                    enum:
                      - true
        required:
          - id
          - name
          - site_id
          - filters
  - name: Customers
    description: |
      A `Customer` represents a guest at a Trybe site.

      A `Customer` is created when a guest creates an account on a Trybe shopfront, places a booking, or is created manually in the Trybe app.
    x-info:
      baseSchema:
        type: object
        title: Customer
        description: A guest record — the long-lived profile that bookings, orders, payments, memberships and marketing preferences attach to. Customers are scoped to a site (and, where configured, an organisation) and may have multiple addresses, payment methods and external IDs. Their email is the natural login identifier when self-service is enabled.
        additionalProperties: false
        properties:
          id:
            $ref: '#/components/schemas/id'
          first_name:
            $ref: '#/components/schemas/first_name'
          last_name:
            $ref: '#/components/schemas/last_name'
          full_name:
            $ref: '#/components/schemas/full_name'
          phone:
            $ref: '#/components/schemas/phone'
          has_password:
            $ref: '#/components/schemas/has_password'
          dob:
            $ref: '#/components/schemas/dob'
          brand_id:
            $ref: '#/components/schemas/brand_id'
          site_id:
            $ref: '#/components/schemas/site_id'
          stripe_id:
            $ref: '#/components/schemas/stripe_id'
          express_stripe_id:
            $ref: '#/components/schemas/express_stripe_id'
          email:
            $ref: '#/components/schemas/email'
          labels:
            type: array
            description: An array of labels associated with this customer
            items:
              $ref: '#/components/schemas/schemas_CustomerLabel'
          preferred_locale:
            $ref: '#/components/schemas/preferred_locale'
          locked_at:
            $ref: '#/components/schemas/locked_at'
          created_at:
            $ref: '#/components/schemas/created_at'
          updated_at:
            $ref: '#/components/schemas/updated_at'
          deleted_at:
            $ref: '#/components/schemas/deleted_at'
          last_active_at:
            $ref: '#/components/schemas/last_active_at'
          email_verified_at:
            $ref: '#/components/schemas/email_verified_at'
          last_check_in:
            type: object
            description: A summary of the last check-in event associated with this customer, or `null` if they have never checked-in.
            nullable: true
            $ref: '#/components/schemas/LastCheckInSummary'
          avatar_id:
            $ref: '#/components/schemas/avatar_id'
          avatar:
            $ref: '#/components/schemas/Media'
            description: The media object of the customer's avatar, or `null` if one hasn't been provided.
            nullable: true
          external_ref:
            $ref: '#/components/schemas/external_ref'
        required:
          - id
          - first_name
          - last_name
          - full_name
          - phone
          - has_password
          - dob
          - brand_id
          - site_id
          - stripe_id
          - express_stripe_id
          - email
          - labels
          - preferred_locale
          - locked_at
          - created_at
          - updated_at
          - deleted_at
          - last_active_at
          - email_verified_at
          - last_check_in
          - avatar_id
          - avatar
          - external_ref
  - name: DepositExposure
    description: |
      The deposit exposure report represents the deposit exposure of all sites on a given date.
  - name: DepositLedger
    description: |
      A report detailing deposit revenue balances.
  - name: DiscountTypes
    description: |
      Discount types
    x-info:
      baseSchema:
        title: DiscountType
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the discount type.
          applicable_for:
            type: string
            description: Where the discount type is able to be applied.
            example: app_and_booking_engine
            enum:
              - app_only
              - app_and_booking_engine
          code:
            type: string
            description: |
              The code for the discount type.
              When the type is a promo code, this will be what the customer enters in on the booking engine to receive their discount, e.g. `SUMMER23`.
              Or, if the discount type is for app use, this is what is used for reporting.
            example: SUMMER23
          description:
            type: string
            description: |
              This provides further details on what the discount type can be used for.
              It's up to the user to provide this.
            example: For 15% off any order placed from Jun-Aug 2023
            nullable: true
          amount_type:
            type: string
            description: |
              The type of discount. For a promo code, this will always be a percentage.
            example: percentage
            enum:
              - monetary
              - percentage
          discount_amount:
            type: integer
            description: |
              The value of the discount to be applied when a discount type is used.
              This can be used as a monetary amount or percentage for an in-app discount type and is set to percentage for a promo code.
            example: 15
            nullable: true
          currency:
            type: string
            description: |
              The currency of the monetary discount to be applied if `amount_type` is set to `monetary` for an in-app discount type.
              This is associated with the site.
            example: gbp
          is_custom_amount:
            type: boolean
            default: false
            example: false
            description: |
              Whether the amount provided is customisable.
              This can only be toggled for in-app discount types.
          valid_from:
            type: string
            format: date
            description: |
              The start date which the promo code is valid from, based on the date the order is submitted.
              This field is null if `applicable_for` is set to `app_only`.
              For a promo code to be valid for use on an order, this must be set.
            example: '2023-06-01'
            nullable: true
          valid_to:
            type: string
            format: date
            description: |
              The end date which the promo code is valid until, based on the date the order is submitted.
              This field is null if `applicable_for` is set to `app_only`.
              This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
            example: '2023-09-01'
            nullable: true
          item_date_from:
            type: string
            format: date
            description: |
              The start date for when the purchased item occurs, based on the date the item is booked for.
              This field is null if `applicable_for` is set to `app_only`.
              This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
            example: '2023-09-01'
            nullable: true
          item_date_to:
            type: string
            format: date
            description: |
              The end date for when the purchased item occurs, based on the date the item is booked for.
              This field is null if `applicable_for` is set to `app_only`.
              This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
            example: '2023-09-30'
            nullable: true
          item_date_weekdays:
            type: array
            description: |
              The days the purchased item takes place on.
              For example, the promo code could be valid for massages which only occur on Mondays.
              By default, this array contains all enum values and the occurrence of the purchased items is not restricted to any days.
            items:
              type: string
              enum:
                - monday
                - tuesday
                - wednesday
                - thursday
                - friday
                - saturday
                - sunday
          item_time_from:
            type: string
            description: |
              The start time for when the purchased item takes place.
              For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
              This field is null if `applicable_for` is set to `app_only`.
              This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
            example: '10:00'
            nullable: true
          item_time_to:
            type: string
            description: |
              The end time for when the purchased item takes place.
              For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
              This field is null if `applicable_for` is set to `app_only`.
              This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
            example: '14:00'
            nullable: true
          valid_offerings:
            type: array
            description: |
              An array of offerings which the promo code is valid for.
              By default, this array is empty and the discount will not be applied to any items in the order.
              If this array includes offerings, the discount will be applied to only those selected items in the order.
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          max_uses:
            type: integer
            description: |
              The maximum number of times the code can be used in total.
              By default, this value is null which means that this number is unlimited.
            example: 100000
            nullable: true
          has_been_redeemed:
            type: boolean
            default: false
            example: false
            description: |
              Whether the promo code has been used by at least one customer.
              If this value is true, the `code` field is no longer editable.
          site_id:
            type: string
            format: uuid
            description: The ID of the site the discount type is associated with.
          created_at:
            type: string
            format: date-time
            description: The date and time the discount type was created.
            example: '2023-01-01T00:00:00Z'
          updated_at:
            type: string
            format: date-time
            description: The date and time the discount type was updated.
            example: '2023-01-01T00:00:00Z'
          deleted_at:
            type: string
            format: date-time
            nullable: true
            description: The date and time the discount type was deleted.
            example: '2023-01-01T00:00:00Z'
        required:
          - id
          - applicable_for
          - code
          - description
          - amount_type
          - discount_amount
          - currency
          - is_custom_amount
          - valid_from
          - valid_to
          - item_date_from
          - item_date_to
          - item_date_weekdays
          - item_time_from
          - item_time_to
          - valid_offerings
          - max_uses
          - has_been_redeemed
          - site_id
          - created_at
          - updated_at
          - deleted_at
  - name: DiscountUsage
    description: |
      The `DiscountUsage` group of reports cover the usage of promo codes and discount types across individual orders and across all orders.
  - name: Equipment
    description: |
      `Equipment` represents physical tools or items required to deliver an appointment (e.g. a steam machine, a massage table). Appointment types declare equipment they need; availability calculations enforce concurrency.
  - name: EscPosConnectors
    description: |
      `EscPosConnector`s are used to connect an Esc/Pos receipt printer to Trybe
  - name: ExitGratuity
    description: |
      Internal endpoints used by the exit-gate flow to offer and
      capture gratuity from guests as they leave the venue.
  - name: ExternalIdTypes
    description: |
      Endpoints for managing external ID types
  - name: FeatureFlags
    description: |
      Application-layer feature flags — the runtime toggles Trybe
      engineering uses to roll out new functionality. Flags can be
      enabled globally, off globally with a per-site opt-in cohort, or
      on globally with a per-site opt-out cohort. Trybe-internal
      callers only; consumers do not normally touch these.
  - name: FiasRelay
    description: |
      Public download feed for the Trybe FIAS relay — the desktop
      helper that bridges Trybe to Opera's FIAS interface for folio
      search and room-charge posting.
  - name: Fiscalisation
    description: Endpoints to carry out fiscalisation operations using a site's configured fiscalisation integration.
  - name: Fiskaltrust
    description: Endpoints used to manage the Fiskaltrust integration
  - name: Fiskaly
    description: Endpoints used to manage the Fiskaly integration
  - name: ForSight
    description: These endpoints are used to manage the For-Sight integration.
  - name: Frontend
    description: Endpoints used by the shopfront.
  - name: Gantner
    description: |
      Gantner endpoints are used to manage Gantner integrations.
  - name: Giftpro
    description: These endpoints are used to manage the Giftpro integration.
  - name: Guestline
    description: Guestline endpoints are used to manage Guestline integrations.
  - name: HConnectIntegration
    description: |
      Sites can be integrated with third-party services. These endpoints allow you to manage these integrations.

      | Name | API Documentation URL | Posts Deposits | Redeems Deposits | Charges to Hotel Rooms/Customers/Folios |
      | --- | --- | --- | --- | --- |
      | HConnect | https://apidocs.hconnect.io/view/15618877/UVyvuZDE | ✅ | ✅ | ✅ |
  - name: HotelRoomTypes
    description: Endpoints to manage hotel room types that are offered through Trybe.
    x-info:
      baseSchema:
        title: HotelRoomType
        description: A bookable category of overnight accommodation (e.g. "Deluxe Double", "Family Suite"). The room type defines pricing rates, occupancy limits and inventory pool that overnight bookings draw from; individual rooms in the property are assigned at check-in time, not at booking time.
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: The ID of the hotel room type.
          name:
            type: string
            description: The name of the hotel room type.
            example: Deluxe Double
          description:
            type: string
            nullable: true
            description: A description of the hotel room type.
            example: Enjoy a relaxing night in our deluxe room.
          external_id:
            type: string
            description: An ID of this room type from the external system.
            example: DDBL
          external_source:
            type: string
            description: The external source of this room type.
            example: pms_name
          images:
            type: array
            description: An array of images of this hotel room type.
            items:
              $ref: '#/components/schemas/Media'
          image:
            type: string
            description: The main image for this hotel room type.
            $ref: '#/components/schemas/Media'
          updated_at:
            type: string
            format: date-time
            description: The time when this hotel room type was last updated.
          site_id:
            type: string
            format: uuid
            description: The ID of the site this hotel room type belongs to.
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation this hotel room type belongs to.
        required:
          - id
          - name
          - description
          - external_id
          - external_source
          - updated_at
          - site_id
          - organisation_id
  - name: Hotsoft
    description: |
      Hotsoft endpoints are used to manage the Hotsoft PMS integration.
  - name: Imports
    description: |
      These endpoints are used to import data into Trybe
    x-info:
      baseSchema:
        type: object
        title: Import
        additionalProperties: false
        properties:
          id:
            type: string
            description: The ID of the import
            format: uuid
          type:
            $ref: ./properties.yml#/type
          status:
            type: string
            description: The status of the import
            enum:
              - validating
              - validated
              - importing
              - imported
              - rolling_back
              - rolled_back
              - errored
            example: running
          total_rows:
            type: integer
            description: The total number of rows in the import
            example: 1000
          imported_rows:
            type: integer
            description: The number of rows that have been imported
            example: 950
          failed_validation_rows:
            type: integer
            description: The number of rows that didn't pass validation
            example: 0
          failed_import_rows:
            type: integer
            description: The number of rows that failed to import
            example: 0
          premier_core_mapping_id:
            type: string
            description: |
              The ID of the [Premier Core mapping](/endpoints/PremierCoreMappings) that was used for this import.

              This field is only present when the `type` is `premier_core`.
            format: object-id
          created_at:
            type: string
            description: The time the import was created
            format: date-time
          updated_at:
            type: string
            description: The time the import was last updated
            format: date-time
          validated_at:
            type: string
            description: The time the import was validated (successful _or_ unsuccessful).
            format: date-time
            nullable: true
          imported_at:
            type: string
            description: The time the import was completed.
            format: date-time
            nullable: true
          rolled_back_at:
            type: string
            description: The time the import was rolled back.
            format: date-time
            nullable: true
          progress:
            type: integer
            description: The percentage of the import that has been completed.
            example: 95
          created_by:
            description: The user who created the import
            $ref: ../schemas.yml#/UserSummary
        required:
          - id
          - type
          - status
          - total_rows
          - failed_validation_rows
          - failed_import_rows
          - imported_rows
          - created_at
          - updated_at
          - started_at
          - completed_at
          - progress
          - created_by
  - name: IntakeFormDeletionPolicy
    description: |
      An `IntakeFormDeletionPolicy` allows you to specify if/when intake-forms are automatically deleted after the associated booking has taken place.
  - name: IntakeForms
    description: Endpoints to manage `IntakeFormSection`s and `IntakeFormQuestion`s.
  - name: IntegrationConfigs
    description: |
      Endpoints to manage config for integrations.
    x-info:
      baseSchema:
        title: IntegrationConfig
        description: The details of the integration config. Properties vary depending on the integration.
        type: object
        additionalProperties: true
        properties:
          id:
            type: string
            format: object-id
            description: The ID of the integration config.
          name:
            type: string
            description: The name of the integration.
            example: Main PMS integration
            nullable: true
          type:
            type: string
            description: The type (category) of integration config.
            example: payments
          provider:
            type: string
            description: A key for the provider of the integration.
            example: guestline_rezlynx
          provider_name:
            type: string
            description: The name of the provider of the integration.
            example: Guestline (Rezlynx)
          enabled:
            type: boolean
            description: Whether the integration config is enabled or not.
            example: false
        required:
          - id
          - type
          - provider
          - provider_name
          - name
          - enabled
  - name: IntegrationOutages
    description: Endpoints to list and view integration outage history (e.g. when Fiskaly or other integrations were unavailable).
  - name: Internal
    description: |
      System-to-system endpoints — not for general API consumption.
      These routes are used by trusted internal services to bootstrap
      a new site's resources and perform housekeeping not exposed via
      the public API surface.
  - name: InternalOrders
    description: |
      System-to-system order endpoints — used by trusted internal
      services that need to read and update orders without the
      site-permission checks applied to the public `Orders` surface.
  - name: InventoryAdjustments
    description: |
      An `InventoryAdjustment` is a positive or negative change to
      the quantity of an inventory product at a location, capturing
      the reason for the change and the user who applied it.
  - name: InventoryBrands
    description: |
      An `InventoryBrand` represents a brand for inventory items.
  - name: InventoryCategories
    description: |
      An `InventoryCategory` represents a category for inventory items.
  - name: InventoryLocations
    description: |
      An `InventoryLocation` is a physical bucket within a site
      against which stock counts and adjustments are recorded — for
      example, "Treatment store", "Retail floor", or "Back of house".
  - name: InventoryOrders
    description: |
      An `InventoryOrder` represents an order for inventory stock.
    x-info:
      baseSchema:
        title: InventoryOrder
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the inventory order.
          status:
            type: string
            description: The status of the inventory order.
            enum:
              - draft
              - submitted
              - received
          purchase_order_number:
            type: string
            description: The purchase order number for this inventory order.
            example: PO123
          supplier_id:
            type: string
            format: uuid
            description: The ID of the supplier for this inventory order.
          supplier_name:
            type: string
            description: The name of the supplier for this inventory order.
            example: Elemis
          supplier_email:
            type: string
            description: An email address for the supplier of this inventory order.
            example: orders@example.com
          subtotal:
            type: integer
            description: The subtotal of the order in the lowest denomination for this order's currency.
            example: 2000
          currency:
            type: string
            description: The currency of the inventory order.
            example: gbp
          item_count:
            type: integer
            description: The total number of items in the inventory order.
            example: 10
          items_added:
            type: boolean
            description: Whether items have been added to the order.
          created_by_id:
            type: string
            format: uuid
            description: The ID of the user who created the inventory order.
            nullable: true
          site_id:
            type: string
            format: uuid
            description: The ID of the site this inventory order belongs to.
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation this inventory order belongs to.
          created_at:
            type: string
            format: date-time
            description: The date and time the inventory order was created.
            example: '2024-06-01T12:00:00Z'
          updated_at:
            type: string
            format: date-time
            description: The date and time the inventory order was last updated.
            example: '2024-06-01T12:00:00Z'
          submitted_at:
            type: string
            format: date-time
            description: The date and time the inventory order was submitted.
            example: '2024-06-01T12:00:00Z'
            nullable: true
          last_submitted_at:
            type: string
            format: date-time
            description: The date and time the inventory order was last submitted.
            example: '2024-06-02T12:00:00Z'
            nullable: true
        required:
          - id
          - status
          - supplier_id
          - supplier_name
          - supplier_email
          - subtotal
          - currency
          - item_count
          - items_added
          - created_by_id
          - site_id
          - organisation_id
          - created_at
          - updated_at
          - submitted_at
          - last_submitted_at
  - name: InventoryProducts
    description: |
      An `InventoryProduct` represents stock in inventory.
    x-info:
      baseSchema:
        title: InventoryProduct
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the inventory product.
          name:
            type: string
            description: The name of the inventory product.
            example: Blissful Body Butter
          description:
            type: string
            description: A description of the inventory product.
            example: A rich, creamy body butter which deeply nourishes the skin, with essential oils.
            nullable: true
          sku:
            type: string
            description: A stock keeping unit (SKU) for the inventory product.
            example: BB-001
            nullable: true
          barcode:
            type: string
            description: A barcode for the inventory product.
            example: 123456789
            nullable: true
          average_cost:
            type: integer
            description: The average cost of the inventory product in the lowest denomination for this product's currency.
            example: 1000
          currency:
            type: string
            description: The currency of the inventory product.
            example: gbp
          reorder_level:
            type: integer
            description: The quantity of this inventory product which should be reordered.
            example: 10
            nullable: true
          stock_level:
            type: number
            description: The quantity of this stock at the site.
            example: 50.5
          stock_value:
            type: integer
            description: The total value of this stock at the site in the lowest denomination for this product's currency.
            example: 5000
          brand_id:
            type: string
            format: uuid
            description: The ID of the brand this inventory product belongs to.
            nullable: true
          brand:
            $ref: '#/components/schemas/InventoryBrand'
            nullable: true
          category_id:
            type: string
            format: uuid
            description: The ID of the category this inventory product belongs to.
            nullable: true
          category:
            $ref: '#/components/schemas/InventoryCategory'
            nullable: true
          site_id:
            type: string
            format: uuid
            description: The ID of the site this inventory product belongs to.
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation this inventory product belongs to.
        required:
          - id
          - name
          - description
          - sku
          - barcode
          - average_cost
          - currency
          - reorder_level
          - stock_level
          - stock_value
          - brand_id
          - category_id
          - site_id
          - organisation_id
  - name: KioskBufferTimes
    description: |
      Kiosk Buffer time rules are used to configure Trybe Kiosk buffer times.
  - name: KioskConfiguration
    description: |
      The Kiosk Configuration is used to configure the Trybe Kiosk.
  - name: KioskDevices
    description: |
      Kiosk Device are used to configure Trybe Kiosk Devices.
  - name: KioskInstructions
    description: |
      Kiosk Instructions are used to configure offering-specific instructions displayed in the Trybe Kiosk.
  - name: Labels
    description: |
      A `Label` is an organisation-wide tag that can be attached to
      customers (and other resources) to categorise them for
      reporting and filtering purposes.
    x-info:
      baseSchema:
        title: Label
        type: object
        additionalProperties: false
        description: |
          A `Label` is an organisation-wide tag that can be attached to customers, orders, and other resources to categorise them for reporting and filtering purposes.
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the label
            example: 000000-000000-000000-000000
          value:
            type: string
            description: The name of the label
            example: VIP
          colour:
            type: string
            description: A hex colour code excluding the preceding \# which this label will be rendered as.
            example: ff6634
          organisation_id:
            type: string
            format: uuid
            description: The organisation which this label belongs to
            example: 000000-000000-000000-000000
          created_at:
            type: string
            format: date-time
            description: The datetime which the label was created
            example: '2021-01-01T00:00:00.000Z'
          updated_at:
            type: string
            format: date-time
            description: The datetime which the label was last updated
            example: '2021-01-01T00:00:00.000Z'
        required:
          - id
          - value
          - colour
          - organisation_id
          - created_at
          - updated_at
  - name: LedgerLinePostings
    description: |
      A `LedgerLinePosting` contains a group of balanced `LedgerLine`'s that Trybe can send to other systems. The `LedgerLinePosting` ensures accurate recording of financial transactions and enables you to monitor the successful postings for data integrity.
    x-info:
      baseSchema:
        type: object
        title: LedgerLinePosting
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: The ID of this ledger line posting.
          site_id:
            type: string
            description: The ID of the site this ledger line posting belongs to.
            format: uuid
          created_at:
            type: string
            format: date-time
            description: The date and time the ledger posting was created.
            example: '2023-05-05T11:38:29+01:00'
          integration:
            type: string
            description: An identifier for the integration the posting was for.
            example: guestline_rezlynx
          integration_name:
            type: string
            description: A user-friendly name for the integration.
            example: Guestline
          integration_is_async:
            type: boolean
            description: Whether the integration works asynchronously.
            example: false
          status:
            type: string
            description: The status of the posting.
            enum:
              - success
              - resolved
              - error
              - in_progress
              - not_started
              - nothing_to_post
          payable:
            $ref: '#/components/schemas/PayableSummary'
          causer:
            $ref: '#/components/schemas/CauserSummary'
          last_error:
            type: string
            description: The last error encountered when attempting to post this record.
          last_error_at:
            type: string
            format: date-time
            description: The date and time of the last error.
            example: '2023-05-05T11:39:21+01:00'
          succeeded_at:
            type: string
            format: date-time
            description: The date and time the posting succeeded.
            example: '2023-05-05T11:39:21+01:00'
          lines:
            type: array
            items:
              $ref: '#/components/schemas/LedgerLine'
        required:
          - id
          - site_id
          - created_at
          - integration
          - integration_name
          - status
          - payable
          - causer
          - lines
  - name: LedgerLines
    description: |
      A `LedgerLine` contains the details of a charge or a revenue.
    x-info:
      baseSchema:
        type: object
        title: LedgerLine
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: The ID of the ledger line.
          gross_amount:
            type: integer
            description: The gross amount of the ledger line.
            example: 10000
          net_amount:
            type: integer
            description: The net amount of the ledger line.
            example: 8333
          type:
            type: string
            description: The type of the ledger line, i.e. a charge (payment or refund) or revenue.
            enum:
              - charge
              - revenue
          description:
            type: string
            description: A description of the ledger line.
            example: Trybe Cash payment [TRY3Z] Jane Jenkins
          revenue_centre:
            type: string
            nullable: true
            description: Contains the revenue centre ID if this line is for revenue.
            example: spa
          revenue_centre_name:
            type: string
            nullable: true
            description: A friendly name for the revenue centre.
            example: Spa
          payment_processor:
            type: string
            nullable: true
            description: A key for the payment processor if this line is for a charge.
            example: manual
          payment_processor_friendly:
            type: string
            nullable: true
            description: A friendly name for the payment processor and type if this line is for a charge.
            example: Manual (Cash)
          mapped_value:
            type: string
            nullable: true
            description: The value that this line's revenue centre or payment processor was mapped to for the integration.
            example: trybe_spa_revenue
          ledger_date:
            type: string
            format: date-time
            description: The date and time the ledger event occurred.
            example: '2023-04-02T00:00:00+01:00'
          currency:
            type: string
            description: The currency of the ledger line. See [Supported Currencies](/endpoints/Meta#metaSupportedCurrencies) for a list of supported currencies.
            example: gbp
          payable:
            $ref: '#/components/schemas/PayableSummary'
            nullable: true
          causer:
            $ref: '#/components/schemas/CauserSummary'
            nullable: true
          status:
            type: string
            description: The status of the ledger line. Lines without a status are assumed to be final.
            nullable: true
            enum:
              - pending
              - final
          created_at:
            type: string
            format: date-time
            description: The date and time the ledger posting was created.
            example: '2023-05-05T11:38:29+01:00'
        required:
          - id
          - gross_amount
          - net_amount
          - type
          - description
          - revenue_centre
          - revenue_centre_name
          - payment_processor
          - payment_processor_friendly
          - ledger_date
          - currency
          - payable
          - causer
          - status
          - created_at
  - name: Marketing
    description: |
      Marketing endpoints — create email lists derived from shop-side
      criteria so the Customer API can mailshot a curated audience.
  - name: MarketingPreferences
    description: |
      A `MarketingPreference` represents a preferred form of communication between an organisation and its customers.
    x-info:
      baseSchema:
        title: MarketingPreference
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the marketing preference
          text:
            type: string
            description: The text of the marketing preference
            example: I want to receive emails about special offers
          locale:
            type: string
            description: |
              The locale this marketing preference's text is written in. A marketing
              preference only ever has one language; to offer the same preference in
              multiple languages, create a separate marketing preference per locale.

              This must be one of the platform's supported locales, which can be retrieved using the [`listMetaSupportedLocales`](/endpoints/Meta#listMetaSupportedLocales) endpoint.
            example: en
          organisation_id:
            type: string
            description: The ID of the organisation this marketing preference is linked to
          created_at:
            type: string
            format: date-time
            description: The date and time which the marketing preference was created
          updated_at:
            type: string
            format: date-time
            description: The date and time which the marketing preference was last updated
        required:
          - id
          - text
          - locale
          - organisation_id
          - created_at
          - updated_at
  - name: Media
    description: |
      A `Media` represents a file uploaded to Trybe.
    x-info:
      baseSchema:
        type: object
        title: Media
        additionalProperties: false
        properties:
          id:
            type: string
            description: |
              Unique identifier of the uploaded media item, returned from
              `createMedia`. Pass this ID into any field that accepts a
              media reference (logos, hero images, product images, etc.).
            format: uuid
          file_name:
            type: string
            description: |
              Original filename of the uploaded asset, preserved as
              provided at upload time. Used for display in the media
              library and as a hint when serving downloads.
            example: super-cool-photo.jpg
          mime_type:
            type: string
            description: The mime type of the media item.
            example: image/jpeg
          original_url:
            type: string
            description: The url of the media resource.
            example: https://example.com/media/super-cool-photo.jpg
          size:
            type: integer
            description: The size of the media item in bytes.
            example: 84256
          url:
            type: string
            description: The url of the converted media resource.
            example: https://example.com/media/super-cool-photo-thumbnail@2x.jpg
        required:
          - id
          - file_name
          - mime_type
          - original_url
          - size
          - url
  - name: MembershipCharges
    description: |
      A `MembershipCharge` represents a charge for a `Membership`.
    x-info:
      baseSchema:
        title: MembershipCharge
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            description: The ID of the membership charge
            format: uuid
          membership:
            description: Summary details of the membership this charge relates to
            $ref: '#/components/schemas/MembershipSummary'
          processor:
            type: string
            description: The processor of the payment
            example: adyen
          processor_data:
            $ref: '#/components/schemas/PaymentProcessorData'
          amount:
            type: integer
            description: The amount of the charge, in the smallest units
            example: 3995
          original_amount:
            type: integer
            description: The original amount of the charge, in the smallest units
            example: 3995
          currency:
            type: string
            description: The code of the currency for the charge
            example: gbp
          tax:
            type: string
            description: The amount of tax calculated for this charge
            example: 1000
          status:
            type: string
            description: The status of the charge
            example: succeeded
          description:
            type: string
            description: A description of the charge
            nullable: true
          can_download_receipt:
            type: boolean
            description: Whether a receipt is available for this charge
          amount_refunded:
            type: integer
            description: The total amount refunded for this charge
          refunded:
            type: boolean
            description: Whether this charge has been fully refunded
          refunds:
            type: array
            description: An array of refunds against this charge
            items:
              $ref: '#/components/schemas/MembershipChargeRefund'
          site_id:
            type: string
            description: The ID of the site this charge belongs to
            format: uuid
          billing_period_from:
            type: string
            format: date
            description: The first date of the billing period
          billing_period_to:
            type: string
            format: date
            description: The last date of the billing period
          processing_at:
            type: string
            format: date-time
            description: The datetime when the charge started processing
          created_at:
            type: string
            format: date-time
            description: The datetime when the charge was created
          updated_at:
            type: string
            format: date-time
            description: The datetime when the charge was last updateed
        required:
          - id
          - membership
          - processor
          - processor_data
          - amount
          - currency
          - tax
          - status
          - description
          - can_download_receipt
          - amount_refunded
          - refunded
          - refunds
          - site_id
          - billing_period_from
          - billing_period_to
          - created_at
          - updated_at
  - name: MembershipCreditRules
    description: |
      A `MembershipCreditRule` represents a rule for issuing credit to members of a `MembershipType`.
    x-info:
      baseSchema:
        title: MembershipCreditRule
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the credit rule
          membership_type_id:
            type: string
            format: uuid
            description: The ID of the membership type this rule relates to
          membership_type:
            $ref: '#/components/schemas/schemas_MembershipTypeSummary'
          coupon_id:
            type: string
            description: The ID of the coupon which will be issued
          coupon_name:
            type: string
            description: The name of the coupon which will be issued
          coupon_description:
            type: string
            description: The description of the coupon which will be issued
          roll_over:
            type: boolean
            description: |
              If true, unused credits will roll over to the next month.
              Otherwise, any unused credits will be marked as expired on the next billing period.
          issue_on_signup:
            type: boolean
            description: |
              If true, the credit will be issued when new customers sign up for the given membership type.
              Otherwise, the credit will be issued only on the monthly billing schedule.
          multi_use:
            type: boolean
            description: |
              If true, the credit can be used an unlimited number of times until the expiry date.
          for_lead_booker_only:
            type: boolean
            description: |
              If true, the credit will only be issued for the lead booker of an order. If false, the credit will be issued for all guests on the order, including non-members.
          issuing_frequency:
            type: string
            enum:
              - billing_cycle
              - P0D
              - P1M
              - P3M
              - P6M
              - P1Y
            description: |
              The frequency that this credit is issued.
              The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P1M
          created_at:
            type: string
            format: date-time
            description: The date and time which the credit rule was created
            example: '2026-01-01T00:00:00+00:00'
          updated_at:
            type: string
            format: date-time
            description: The date and time which the credit rule was last updated
            example: '2026-01-01T00:00:00+00:00'
        required:
          - id
          - membership_type_id
          - coupon_id
          - coupon_name
          - coupon_description
          - roll_over
          - issue_on_signup
          - multi_use
          - for_lead_booker_only
          - issuing_frequency
          - created_at
          - updated_at
  - name: MembershipRates
    description: |
      A `MembershipRate` represents the how a `Membership` is billed.
    x-info:
      baseSchema:
        title: MembershipRate
        type: object
        additionalProperties: false
        required:
          - id
          - billing_frequency
          - created_at
          - currency
          - default_duration
          - joining_fee
          - membership_type_id
          - name
          - notice_period
          - price
          - processors
          - private
          - updated_at
        properties:
          id:
            type: string
            description: The ID of the membership rate
            format: uuid
          membership_type_id:
            type: string
            description: The ID of the `MembershipType` which this rate belongs to
            format: uuid
          name:
            type: string
            description: The name of the membership rate
            example: Standard rate
          currency:
            type: string
            description: The currency which all monetary values of this rate are in, uppercase, in the ISO4217 format
            example: GBP
          price:
            type: number
            description: The price of the rate as an integer of the smallest unit eg pence. This is charged to the customer every billing period according to the `billing_frequency`
            example: 5000
          joining_fee:
            type: number
            description: The price of the joining fee as an integer of the smallest unit eg pence.
            example: 1000
          billing_frequency:
            type: string
            description: |
              The frequency that this membership is billed.
              The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P1M
          processors:
            type: array
            items:
              type: string
          default_duration:
            type: string
            nullable: true
            description: |
              The default duration of the membership. This is used when a customer signs themselves up for a membership.
              The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P1Y
          notice_period:
            type: string
            nullable: true
            enum:
              - P7D
              - P14D
              - P1M
              - P3M
              - P6M
              - P1Y
              - null
            description: |
              How much notice a customer must give to cancel a membership on this rate.
              The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
              When null, no notice is required.
            example: P1M
          private:
            type: boolean
            description: |
              Whether this `MembershipRate` is private. If public, it will be selectable on the self-signup flow.
            example: true
          created_at:
            type: string
            format: date-time
            description: The datetime which the rate was created
          updated_at:
            type: string
            format: date-time
            description: The datetime which the membership was last updated
  - name: MembershipTypes
    description: |
      A `MembershipType` represents a type of membership. This encompasses the credits which the member receives.
    x-info:
      baseSchema:
        type: object
        title: MembershipType
        additionalProperties: false
        properties:
          id:
            type: string
            description: The ID of the membership type
            format: uuid
          name:
            type: string
            description: The name of the membership type
            example: Gold tier
          description:
            type: string
            description: The description of the membership type
            example: Enjoy exclusive benefits as part of being a member in our Gold tier
            nullable: true
          terms:
            type: string
            description: Terms and conditions of the membership type
            nullable: true
          brand_id:
            type: string
            description: The ID of the brand this type is linked to
            format: uuid
          offline_payments:
            type: boolean
            description: |
              Whether this MembershipType takes "offline" payments. If true, the monthly fee won't automatically be collected
              using Stripe, which can be useful if a different provider is used for collecting direct debits. You'll need to
              manually manage the membership status.
          disable_confirmation_email:
            type: boolean
            description: |
              Whether to disable sending the confirmation email when a membership is confirmed.
          private:
            type: boolean
            deprecated: true
            description: |
              Whether this `MembershipType` is private or not.

              When a `MembershipType` is private, it won't be shown to users on the site's shop frontend.

              This field is deprecated and has been superceded by `visibility`.
          visibility:
            type: string
            description: |
              The visibility of the `MembershipType` on the site's shop frontend.
            enum:
              - public
              - private
              - link_only
          minimum_start_date:
            type: string
            format: date-time
            description: The minimum start date for a membership of this type.
            nullable: true
          min_members:
            type: integer
            description: The minimum number of members required to create a membership of this type
            example: 2
          max_members:
            type: integer
            description: The maximum number of members allowed to create a membership of this type
            example: 4
          rates:
            description: The public MembershipRates for this type, or if a `MembershipSignupToken` was passed, the rate linked to that.
            type: array
            items:
              $ref: '#/components/schemas/MembershipRate'
          revenue_schedule:
            description: The schedule that revenues for this membership should be created, as an [RRULE](https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html) string
            type: string
            example: FREQ=WEEKLY
            nullable: true
          created_at:
            type: string
            format: date-time
            description: The datetime which the membership type was created
          updated_at:
            type: string
            format: date-time
            description: The datetime which the membership type was last updated
          deleted_at:
            type: string
            format: date-time
            description: The datetime which the membership type was archived, or null if it isn't archived.
            nullable: true
        required:
          - id
          - name
          - description
          - terms
          - brand_id
          - offline_payments
          - disable_confirmation_email
          - private
          - minimum_start_date
          - min_members
          - max_members
          - rates
          - revenue_schedule
          - created_at
          - updated_at
          - deleted_at
  - name: Memberships
    description: |
      A `Membership` represents a membership belonging to one or more `Customer`s.
    x-info:
      baseSchema:
        title: Membership
        type: object
        additionalProperties: false
        properties:
          id:
            description: The ID of the membership
            type: string
            format: uuid
          attention_reason:
            description: A string describing what kind of action needs to take place
            type: string
            enum:
              - no_mandate
              - setup_unpaid
              - mandate_revoked
              - payment_failed
              - payment_disputed
              - payment_outstanding
              - site_id
          basket_id:
            description: The basket ID which was used to purchase this membership, if applicable.
            type: string
            format: mongo-id
          customer:
            type: object
            $ref: '#/components/schemas/Customer'
          end_date:
            description: The date which the membership ends
            type: string
            format: date-time
            nullable: true
          external_ref:
            description: An external reference for this membership.
            type: string
          members:
            type: array
            items:
              $ref: '#/components/schemas/MemberSummary'
          membership_number:
            description: |
              The unique membership number of the lead member. This is always a 10 digit numeric string.
              Since this field only relates to the lead member, this is now deprecated.
              Instead, find the membership for the relevant customer in the `members` array.
            type: string
            example: '1234567890'
            deprecated: true
          next_billing_date:
            description: The date which the membership will next be billed
            type: string
            format: date-time
            nullable: true
          next_charge:
            description: |
              A summary of the next charge that's due for this membership.

              This property is only populated when the membership was retrieved using the `[getCustomerMemberships](/endpoints/Customers#getCustomerMemberships) endpoint.
            type: object
            $ref: '#/components/schemas/MembershipChargeSummary'
            nullable: true
          payment_method:
            title: PaymentMethod
            description: |
              Details about the payment method attached to this membership. This payment method
              is used to take payment on the monthly billing period. If a payment method hasn't
              been set up, this will be null.
            type: object
            nullable: true
            additionalProperties: false
            properties:
              id:
                description: The ID of the payment method this membership uses for
                type: string
              type:
                description: The type of payment method.
                type: string
                enum:
                  - card
                  - direct_debit
              last_4:
                description: The last 4 digits of the long card number or the bank account number.
                type: string
              status:
                description: When the payment method is a Direct Debit mandate, the status shows whether the mandate is usable or not
                type: string
                example: revoked
              card_brand:
                description: The brand of the card
                type: string
                example: amex
          rate:
            type: object
            $ref: '#/components/schemas/MembershipRate'
          site_id:
            description: The ID of the site this membership belongs to
            type: string
            format: uuid
          source:
            description: Where the membership was created
            type: string
            enum:
              - self_signup
              - app
              - import
              - unknown
          start_date:
            description: The date which the membership starts
            type: string
            format: date-time
          status:
            type: string
            enum:
              - active
              - needs_dd_mandate
              - needs_attention
              - reserved
              - inactive
              - expired
              - upcoming
          status_updated_at:
            type: string
            format: date-time
          type:
            type: object
            $ref: '#/components/schemas/MembershipType'
          payment_details_url:
            type: string
            description: A URL to a page where the member can provide their payment details.
          created_at:
            description: The datetime which the membership was created
            type: string
            format: date-time
        required:
          - id
          - attention_reason
          - basket_id
          - end_date
          - external_ref
          - members
          - membership_number
          - next_billing_date
          - payment_method
          - rate
          - site_id
          - source
          - start_date
          - status
          - status_updated_at
          - type
          - created_at
  - name: MessageFragments
    description: |
      A `MessageFragment` is a reusable block of email copy that is
      concatenated into a transactional email at send time. Fragments
      are scoped per site, filtered by `message_type`, and can be
      further limited to specific offerings or membership types.
    x-info:
      baseSchema:
        title: MessageFragment
        type: object
        additionalProperties: false
        description: |
          A `MessageFragment` is a reusable block of HTML/Markdown content
          that is concatenated into transactional emails (booking
          confirmations, reminders, follow-ups, etc.). Fragments are scoped
          to a site, can be filtered by `message_type`, and can be limited
          to specific offerings or membership types so that copy is
          tailored to the customer's context.

          At send time, the messaging pipeline pulls every fragment whose
          `message_type` matches the message being sent and whose
          `offerings` and `permitted_membership_type_ids` filters are
          satisfied, sorts them by ascending `priority`, and renders them
          inline into the email body.
        properties:
          id:
            type: string
            format: mongo-id
            description: Unique identifier of the message fragment.
            example: 65d4a6f7f4c1b22a3c5d4e8a
          name:
            type: string
            description: |
              Internal label for the fragment, shown in the admin UI when
              authoring email templates. Not visible to customers.
            example: Spa - arrival instructions
          message_type:
            type: string
            description: |
              Which transactional email this fragment is included in.
              Fragments are only rendered into the matching message type.
            enum:
              - basket_cancelled
              - basket_confirmed
              - basket_follow_up
              - basket_item_cancelled
              - basket_reminder
              - order_summary
              - pay_by_link_request
              - appointment_enquiry_confirmed
              - visit_prompt
              - membership_welcome
              - membership_cancelled
              - voucher_recipient
              - membership_enquiry_confirmed
              - new_order
              - new_enquiry
            example: basket_confirmed
          message:
            type: string
            nullable: true
            description: |
              The body of the fragment. Accepts a restricted subset of HTML
              (basic block and inline tags) which is sanitised on save.
              Liquid-style placeholders such as `{{ customer.first_name }}`
              and `{{ booking.starts_at }}` are interpolated when the email
              is rendered.
            example: |
              <p>Hi {{ customer.first_name }} - we're looking forward to
              seeing you on {{ booking.starts_at|date }}. Please arrive
              15 minutes early to check in at reception.</p>
          priority:
            type: integer
            nullable: true
            description: |
              Render order within a message. Fragments are concatenated in
              ascending `priority` order, so lower numbers appear earlier
              in the email body. Use to control which paragraph leads.
            example: 10
          offerings:
            type: array
            description: |
              Offerings this fragment applies to. When empty, the fragment
              applies to every offering at the site (a global fallback).
              When non-empty, the fragment is only included if the
              message's booking contains at least one matching offering.
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          permitted_membership_type_ids:
            type: array
            nullable: true
            description: |
              Optional list of `MembershipType` IDs. When set, the fragment
              is only rendered for customers who hold an active membership
              of one of these types - useful for member-only welcome copy,
              loyalty perks, or upgrade prompts. Empty/null means no
              membership filter applies.
            items:
              type: string
              format: mongo-id
            example:
              - 65a1c4f7f4c1b22a3c5d1234
          site_id:
            type: string
            format: uuid
            description: |
              Site the fragment belongs to. Fragments are authored
              per-site so each location can tailor its email copy.
          organisation_id:
            type: string
            format: uuid
            description: Organisation that owns the site.
        required:
          - id
          - name
          - message_type
          - message
          - priority
          - offerings
          - permitted_membership_type_ids
          - site_id
          - organisation_id
  - name: Meta
    description: These endpoints provide metadata about the Trybe platform
  - name: Mews
    description: These endpoints are used to manage the Mews integration for the site.
  - name: MyAccount
    description: |
      Self-service endpoints used by the shopfront for the
      currently-authenticated `Customer` — viewing their charges,
      credits, memberships, contraindications, payment methods and
      marketing preferences.
  - name: Notifications
    description: |
      An in-product notification feed for users, scoped per site. Use
      these endpoints to list, group, mark as read/unread, and
      acknowledge notifications raised by integrations and background
      jobs.
  - name: OfferingAvailability
    description: Endpoints for retrieving offering availability.
  - name: OfferingSets
    description: |
      An `OfferingSet` groups offerings together so they can be referenced in other places.
  - name: Offerings
    description: These endpoints are used to interact with offerings.
  - name: Onboarding
    description: These endpoints are used to provide visibility of onboarding progress to new sites.
  - name: Orders
    description: |
      An `Order` is the record of a completed purchase — items,
      guests, payments, vouchers, refunds. Orders normally arrive
      here by being submitted through a [Basket](/endpoints/Baskets),
      which runs the booking-engine validation suite (availability,
      reservation policies, deposits, intake forms) and reserves the
      bookings server-side.

      The endpoints in this section behave like the basket endpoints
      in shape but are designed for **internal callers producing or
      adjusting orders directly**, bypassing the booking-engine
      validation. Use them to backfill a historical sale, record an
      off-platform booking, fix up a customer's order after the
      fact, or refund / re-charge against a previously-submitted
      order.

      The basket id (when there was one) is preserved on the order
      as `basket_id` so you can trace either way. See
      [Basket vs Order](/guides/basket-and-checkout#basket-vs-order--whats-the-difference)
      in the basket-and-checkout guide for the contrast end-to-end.
    x-info:
      baseSchema:
        title: Order
        description: |
          A customer order containing items and payments.
          This format replaces an older version of the order schema, and must be requested
          explicitly by passing `generic_items_array=true` as a query parameter.
        type: object
        additionalProperties: false
        properties:
          id:
            description: The ID of the order.
            type: string
            format: object-id
          applied_promo_code:
            description: The summary of the promo code applied to an order.
            $ref: '#/components/schemas/AppliedPromoCode'
          applied_promo_code_discount_total:
            type: integer
          applied_promo_code_id:
            type: string
            format: object-id
            nullable: true
          booking_items:
            type: array
            items:
              $ref: '#/components/schemas/BookingItem'
          booking_items_end_date:
            type: string
            format: date
            nullable: true
          booking_items_start_date:
            type: string
            format: date
            nullable: true
          booking_items_span_multiple_days:
            type: boolean
          coupon_codes:
            description: An array of coupon codes applied to the order.
            type: array
            items:
              $ref: '#/components/schemas/CouponSummary'
          currency:
            $ref: '#/components/schemas/properties_currency'
          customer_id:
            description: The ID of the customer the order belongs to.
            type: string
            nullable: true
            format: uuid
          customer_tax_details:
            $ref: '#/components/schemas/CustomerTaxDetails'
          discount_total:
            description: The total value of all applied order-level discounts.
            type: integer
            example: 100
          discounts:
            description: A list of all applied order-level discounts.
            type: array
            items:
              $ref: '#/components/schemas/Discount'
          email:
            description: The email address of the customer.
            type: string
            nullable: true
            example: janedoe@example.com
          external_ids:
            description: An array of external IDs applied to the order.
            type: array
            items:
              $ref: '#/components/schemas/ExternalIdValue'
          external_ref:
            description: An external reference for the order, if set.
            type: string
            nullable: true
            example: ABC-123
          external_visit_ref:
            description: An external visit reference for the order, if set.
            type: string
            nullable: true
            example: RES1234
          first_name:
            description: The first name of the customer.
            type: string
            nullable: true
            example: Jane
          guests:
            type: array
            items:
              $ref: '#/components/schemas/Guest'
          intake_form_required:
            description: True if an intake form is required for this order.
            type: boolean
            example: true
          intake_form_url:
            description: The url for the intake form for this order. Only returned on show and submission.
            nullable: true
            type: string
            example: https://demo.try.be/intake-form
          intake_forms_complete:
            description: Whether all intake forms for the order have been completed.
            type: boolean
            example: true
          integration_config_id:
            description: The ID of the integration config associated with this order.
            type: string
            example: 5f344d756e7f2e7d3f2e4b82
          is_customer_required:
            description: True if a customer needs to be set for this order.
            type: boolean
            example: true
          is_locked:
            description: Whether the order is locked.
            type: boolean
            example: false
          is_promo_code_discount_applied:
            type: boolean
          items:
            type: array
            items:
              $ref: '#/components/schemas/schemas_Item'
          items_status:
            description: A summary of the confirmation status of items within the order.
            type: string
            example: confirmed
            enum:
              - confirmed
              - pending_confirmation
          labels:
            type: array
            items:
              $ref: '#/components/schemas/schemas_Label'
          last_name:
            description: The last name of the customer.
            type: string
            nullable: true
            example: Doe
          locked_at:
            description: The date the order was locked at.
            type: string
            format: date-time
            nullable: true
            example: '2019-01-15T12:00:00+01:00'
          net_total:
            description: The net total of all items in the order.
            type: integer
            example: 8000
          order_ref:
            description: The order reference associated with this booking.
            type: string
            nullable: true
            example: TRY00
          organisation_id:
            description: The ID of the organisation the order belongs to.
            type: string
            format: uuid
          outstanding_payment_amount:
            type: integer
          package_items:
            type: array
            items:
              $ref: '#/components/schemas/OrderPackageItem'
          payment_totals:
            $ref: '#/components/schemas/PaymentTotals'
          payments:
            description: A list of all payments against this order.
            type: array
            items:
              $ref: '#/components/schemas/Payment'
          phone:
            description: The customer's phone number.
            type: string
            nullable: true
            example: '+447727123456'
          post_to_room_config:
            title: PostingRoom
            $ref: '#/components/schemas/PostingRoom'
          promo_code_applied_at:
            type: string
            format: date-time
          promo_code_applied_by:
            $ref: '#/components/schemas/UserSummary'
          purchase_items:
            type: array
            items:
              $ref: '#/components/schemas/PurchaseItem'
          sales_channel:
            description: The sales channel of this order.
            $ref: '#/components/schemas/schemas_SalesChannel'
          service_charge:
            $ref: '#/components/schemas/ServiceCharge'
          site_id:
            description: The ID of the site the order belongs to.
            type: string
            format: uuid
          special_requests:
            description: Any customer requests relating to the order.
            type: string
            nullable: true
            example: I would like the Blue Room please
          stage:
            description: The current stage of the order.
            type: string
            nullable: true
            enum:
              - not_arrived
              - arrived
              - in_treatment
              - checked_out
          status:
            $ref: '#/components/schemas/Status'
          submit_auth_amount:
            type: integer
            nullable: true
          submit_payment_amount:
            type: integer
            nullable: true
          submitted_at:
            description: The time and date that the basket was submitted (confirmed).
            type: string
            format: date-time
            nullable: true
            example: '2020-02-24T12:00:00+01:00'
          submitted_by:
            description: Details of the user who submitted the order, if applicable.
            $ref: '#/components/schemas/UserSummary'
          taxes:
            type: array
            items:
              $ref: '#/components/schemas/TaxAmount'
          tip_amount:
            description: The total amount of tip against the order.
            type: integer
            example: 1050
          tips:
            description: An array of individual tips applied to the order.
            type: array
            items:
              $ref: '#/components/schemas/Tip'
          total_cost:
            type: integer
          total_paid_or_authed:
            type: integer
          total_tax:
            description: The total tax amount of all items in the order.
            type: integer
            example: 2000
          totals:
            $ref: '#/components/schemas/schemas_Totals'
          visit:
            $ref: '#/components/schemas/OrderVisitSummary'
          voucher_codes:
            description: An array of discount-type voucher codes applied to the basket. Monetary vouchers are included as payments.
            type: array
            items:
              $ref: '#/components/schemas/VoucherSummary'
          created_at:
            description: The time and date that the basket was created.
            type: string
            format: date-time
            example: '2020-02-24T12:00:00+01:00'
          updated_at:
            description: The time and date that the basket was last updated.
            type: string
            format: date-time
            example: '2020-02-24T12:00:00+01:00'
        required:
          - id
          - applied_promo_code_id
          - booking_items_end_date
          - booking_items_start_date
          - coupon_codes
          - currency
          - customer_id
          - discount_total
          - discounts
          - email
          - first_name
          - guests
          - is_customer_required
          - is_locked
          - items_status
          - labels
          - last_name
          - net_total
          - order_ref
          - organisation_id
          - outstanding_payment_amount
          - payment_totals
          - payments
          - phone
          - sales_channel
          - service_charge
          - site_id
          - special_requests
          - status
          - submit_auth_amount
          - submit_payment_amount
          - taxes
          - tip_amount
          - tips
          - total_cost
          - total_paid_or_authed
          - total_tax
          - totals
          - visit
          - created_at
          - submitted_at
          - updated_at
  - name: OrganisationReports
    description: Endpoints for organisation-level reports
  - name: Organisations
    description: |
      An `Organisation` is the top-level account that owns one or more
      `Brand`s and their `Site`s — the unit of contract, billing, and
      cross-site user-access management. The endpoints in this section
      cover the resources that belong to an organisation rather than
      to any single site (categories, labels, custom payment types,
      revenue centres, etc.).
    x-info:
      baseSchema:
        title: Organisation
        type: object
        additionalProperties: false
        description: |
          Top-level account that owns one or more `Brand`s and their
          `Site`s. The organisation is the unit of contract, billing, and
          cross-site user-access management.
        properties:
          id:
            type: string
            format: uuid
            description: Stable identifier for the organisation.
          name:
            type: string
            description: |
              Display name of the organisation as it appears in
              Trybe-internal tooling and on contracts. Not normally surfaced
              to end customers, who see the brand or site name instead.
          created_at:
            type: string
            format: date-time
            description: When the organisation was provisioned in Trybe.
        required:
          - id
          - name
          - created_at
  - name: Overnights
    description: |
      A collection of API endpoints for getting availability and metadata for booking an overnight stay.
  - name: PMS
    description: Endpoints for working with a PMS integration.
  - name: PacesetterIntegration
    description: |
      Endpoints for managing a `Site`'s Pacesetter SSO integration, which allows
      members to be signed in to the shop from Pacesetter's system without
      re-entering their details.
  - name: Packages
    description: |
      A `Package` represents a collection of `Offering`s that can be purchased together.
  - name: PartnerConfigs
    description: |
      A `PartnerConfig` captures a site's relationship with an
      external distribution partner — typically an OTA or third-party
      booking engine. Each config restricts which `Offering`s are
      sellable through that partner and carries its own set of
      `PartnerAvailabilityRule`s, so an OTA can be capped at a
      smaller share of inventory than the site itself sells.
  - name: PaymentMethods
    description: A `PaymentMethod` represents a customer's payment method, such as a card or direct debit.
    x-info:
      baseSchema:
        title: PaymentMethod
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the payment method
          payment_method_id:
            type: string
            description: The processor's ID for the payment method
            example: pm_3K6a0RGysTOePye00nkob5Pi
          name:
            type: string
            description: The name of the payment method
            example: My debit card
          type:
            type: string
            enum:
              - card
              - direct_debit
            description: The type of payment method
          status:
            type: string
            description: When the payment method is a Direct Debit mandate, the status shows whether the mandate is usable or not
            example: revoked
          cardholder_name:
            type: string
            description: The cardholder name, or for direct debits, the name of the account holder
            example: Jane Doe
          card_brand:
            type: string
            description: The brand of the card
            example: amex
          card_country:
            type: string
            description: The country where the card was issued
            example: gb
          card_funding:
            type: string
            description: The type of funding for this card
            example: credit
          card_expiry:
            type: string
            description: The expiry month and year for this card
            example: 08/22
          last_4:
            type: string
            description: The last 4 digits of the long card number, or for direct debits, the last 4 digits of the account number
            example: '1234'
          processor:
            type: string
            description: The ID of processor where this payment method is stored
            example: stripe
          created_at:
            type: string
            format: date-time
            description: The datetime which the payment method was created
            example: '2025-01-01T00:00:00+00:00'
          updated_at:
            type: string
            format: date-time
            description: The datetime which the payment method was last updated
            example: '2025-01-01T00:00:00+00:00'
          revoked_at:
            type: string
            format: date-time
            description: The datetime which the payment method was revoked
            example: '2025-01-01T00:00:00+00:00'
        required:
          - id
          - payment_method_id
          - name
          - type
          - status
          - cardholder_name
          - card_brand
          - card_country
          - card_funding
          - card_expiry
          - last_4
          - processor
          - created_at
          - updated_at
  - name: Payments
    description: |
      A `Payment` represents a single charge, refund, or balance
      movement attached to an `Order` — the record of money owed,
      taken, returned, or moved between credit buckets for a given
      purchase.

      Payments don't live in isolation: they're always created,
      listed, charged and refunded **against an Order**. The
      operations that produce + manage payments are documented in
      the [Orders](/endpoints/Orders) section, alongside the rest of
      the order lifecycle. This page is the canonical reference for
      the `Payment` object's shape — what fields you'll see on a
      `payment.complete` webhook, on a list-order-payments response,
      or on the per-order detail view.

      The most-used flow is `createOrderPayment` (record an intent
      to pay) → `actionChargeOrderPayment` (capture the money) →
      `payment.complete` webhook (delivery-side confirmation). See
      [Build a basket and check out](/guides/basket-and-checkout)
      for the end-to-end walkthrough.
    x-info:
      baseSchema:
        title: Payment
        type: object
        description: An instance of a payment against an order.
        additionalProperties: false
        properties:
          id:
            description: The ID of the item to be added.
            type: string
            format: object-id
          amount:
            description: The amount of the payment, in the lowest denomination
            type: integer
            example: 10000
          capture_method:
            description: At what point the payment amount will be captured
            type: string
            nullable: true
            example: automatic
          chargebacks:
            type: array
            items:
              $ref: '#/components/schemas/Chargeback'
          currency:
            description: The currency code for the amount
            $ref: '#/components/schemas/properties_currency'
          details_source:
            description: How the payment method will be provided
            type: string
            nullable: true
            example: pay_by_link
          failure_reason:
            description: If present, provides a human-readable explanation for the failure.
            type: string
            nullable: true
            example: Suspected fraud
          item_revenues:
            description: How the payment amount is allocated across the order's items and revenue centres. Null for payments taken before item revenue allocation was enabled — such payments cannot support item-level operations like partial charge to room.
            type: array
            nullable: true
            items:
              $ref: '#/components/schemas/PaymentItemRevenue'
          order_ref:
            type: string
            nullable: true
          paid_at:
            description: The time and date that the payment was paid.
            type: string
            format: date-time
            nullable: true
            example: '2020-02-24T12:00:00+01:00'
          payable_id:
            type: string
            format: object-id
          payable_type:
            type: string
          processor:
            description: The payment processor to be used for the payment
            type: string
            example: stripe
          processor_data:
            description: A dictionary of processor-specific data
            type: object
            additionalProperties: true
          processor_id:
            type: string
            format: object-id
          processor_type:
            type: string
            nullable: true
          refundable_amount:
            description: The amount of the payment that may be refunded.
            type: number
            example: 3500
          refunds:
            type: array
            items:
              $ref: '#/components/schemas/Refund'
          status:
            description: The current status of the payment
            type: string
            enum:
              - cancelled
              - expired
              - failed
              - paid
              - payment_method_charged
              - payment_method_stored
              - pending
              - ready_for_capture
              - requires_action
          created_at:
            description: The time and date that the payment was created.
            $ref: '#/components/schemas/createdAt'
        required:
          - id
          - amount
          - capture_method
          - currency
          - details_source
          - item_revenues
          - paid_at
          - payable_id
          - payable_type
          - processor
          - processor_id
          - processor_data
          - processor_type
          - refundable_amount
          - refunds
          - status
          - created_at
  - name: Payouts
    description: Endpoints for working with Trybe Pay payouts to a client's bank account.
  - name: Permissions
    description: Endpoints to manage user permissions in Trybe.
  - name: PractitionerRotas
    description: Endpoints to manage Practitioner Rotas in Trybe.
  - name: PractitionerTags
    description: |
      A `PractitionerTag` is a free-form label that can be attached to
      one or more `Practitioner`s within an organisation. Tags are
      used to group practitioners for reporting, calendar filtering,
      and assignment to offerings that require particular skills.
  - name: Practitioners
    description: |
      A `Practitioner` is a bookable staff member — typically a
      therapist, instructor, or stylist — that appointments and
      sessions can be assigned to. Practitioners own a working rota,
      optional commission rules, and the set of appointment / session
      types they're qualified to deliver. The booking flow filters
      availability by practitioner, and order line items record the
      practitioner who delivered the service for reporting and payroll.
    x-info:
      baseSchema:
        title: Practitioner
        description: A bookable staff member — typically a therapist, instructor or stylist — that appointments and sessions can be assigned to. Practitioners own a working rota, optional commission rules, and the set of session/appointment types they are qualified to deliver.
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: |
              Stable identifier for the practitioner. Used when assigning
              sessions, appointments and rotas to the practitioner, and when
              the booking storefront resolves a slot to a specific staff
              member.
            example: 5dcb47800000000000000000
          appointment_restrictions:
            type: array
            items:
              $ref: '#/components/schemas/PractitionerAppointmentRestriction'
          avatar:
            $ref: '#/components/schemas/Media'
          signature:
            description: |
              `Media` to use as the practitioner's signature image. Shown
              on documents and receipts that require a practitioner
              signature. Absent when no signature has been uploaded.
            $ref: '#/components/schemas/Media'
          can_offer_tags:
            type: array
            items:
              type: string
          gender:
            type: string
            nullable: true
            description: |
              Self-identified gender of the practitioner, surfaced to guests
              who filter the booking storefront by practitioner gender. Free
              text — common values are `female`, `male` and `non-binary`.
              `null` when the practitioner hasn't supplied a value.
            example: female
          name:
            type: string
            description: |
              Public display name of the practitioner. Shown to guests on
              the booking storefront and on receipts. Should be the name the
              practitioner wants to appear in front of guests — typically
              first name plus last initial or full name.
            example: Jane Doe
          registration_number:
            type: string
            nullable: true
            description: |
              Optional registration or license number for the practitioner.
              Used to track professional credentials or qualifications.
            example: A123
          organisation_id:
            type: string
            format: uuid
            description: |
              Organisation the practitioner belongs to. Practitioners are
              scoped to a single organisation and are not visible to API
              callers from other organisations.
            example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
          site_ids:
            type: array
            items:
              type: string
              format: uuid
          tag_ids:
            type: array
            items:
              type: string
          tags:
            type: array
            items:
              $ref: '#/components/schemas/Tag'
          zones:
            type: array
            items:
              $ref: '#/components/schemas/Zone'
          commission_package_id:
            type: string
            format: mongo-id
            description: |
              The commission package to use for this practitioner. If not set, the practitioner's default commission package will be the site's default commission package (as defined by `ShopSite.default_commission_package_id`).
            nullable: true
          external_id:
            type: string
            nullable: true
            description: |
              Optional external identifier for the practitioner, used to
              correlate this record with an entry in a third-party system
              (e.g. a PMS, payroll provider, or CRM). Not interpreted by
              the platform — treated as an opaque string.
            example: EXT-001
          user_id:
            type: string
            format: uuid
            nullable: true
            description: |
              Staff `User` linked to this practitioner record, if any.
              Linking lets the user manage their own rota and view their
              appointments from the staff console. `null` for practitioners
              that don't have a login account.
            example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
          created_at:
            $ref: '#/components/schemas/createdAt'
          updated_at:
            $ref: '#/components/schemas/updatedAt'
        required:
          - id
          - appointment_restrictions
          - can_offer_tags
          - external_id
          - name
          - organisation_id
          - site_ids
          - tag_ids
          - tags
          - zones
          - user_id
          - created_at
          - updated_at
  - name: PremierCoreMappings
    description: |
      A `PremierCoreMapping` is used to map a resource from Premier Core to a resource in Trybe for importing data.
  - name: Products
    description: |
      A `Product` represents a physical product that can be sold at a site.
    x-info:
      baseSchema:
        type: object
        title: Product
        additionalProperties: false
        properties:
          id:
            type: string
            description: The ID of the product
            format: mongo-id
          name:
            type: string
            description: The name of this product
            example: Dan's Hand Moisturiser
          currency:
            type: string
            description: The ISO-4217 currency code in lower case
            example: gbp
          description:
            type: string
            description: A description of the product
            example: For silky soft hands
            nullable: true
          external_id:
            type: string
            nullable: true
            description: An external identifier for the product.
          product_code:
            type: string
            description: A custom product code for the product.
            example: MAS123
            nullable: true
          price_from:
            type: integer
            description: The lowest price for the product as an integer of the smallest unit eg pence.
            example: 1000
            nullable: true
          price_to:
            type: integer
            description: The highest price for the product as an integer of the smallest unit eg pence.
            example: 5000
            nullable: true
          standard_price:
            type: integer
            description: The standard price for the product as an integer of the smallest unit eg pence. `null` if a standard price hasn't been configured — this is distinct from a price of zero.
            example: 5000
            nullable: true
          barcode:
            type: string
            description: The barcode of the product
            example: 5013635312160
            nullable: true
          inventory_product_id:
            type: string
            description: |
              The ID of the inventory product if this product is associated to one.
            format: object-id
            nullable: true
          image:
            $ref: '#/components/schemas/Media'
          offered_online:
            type: boolean
            description: Whether this product is available online
          private:
            type: boolean
            description: Whether this product is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
          site_id:
            type: string
            description: The ID of the site this product belongs to
            format: uuid
          tag_ids:
            type: array
            items:
              type: string
            deprecated: true
          tags:
            type: array
            deprecated: true
            items:
              type: object
              additionalProperties: false
              title: ProductTag
              properties:
                id:
                  type: string
                  format: object-id
                  description: The ID of the tag
                name:
                  type: string
                  description: The name of the tag
                  example: Moisturisers
                organisation_id:
                  type: string
                  description: The organisation ID which this tag belongs to
                  format: uuid
              required:
                - id
                - name
                - organisation_id
          category_ids:
            type: array
            description: An array of category IDs that this product belongs to
            items:
              type: string
              format: uuid
          categories:
            type: array
            description: An array of categories that this product belongs to
            items:
              type: object
              additionalProperties: false
              title: ProductCategory
              properties:
                id:
                  type: string
                  format: object-id
                  description: The ID of the category
                name:
                  type: string
                  description: The name of the category
                  example: Moisturisers
              required:
                - id
                - name
          price_rules:
            type: array
            description: The rules defining prices for this product
            items:
              $ref: '#/components/schemas/ProductPriceRule'
          revenue_centre:
            type: string
            description: The revenue centre to assign revenue to for this product
            example: spa
          customer_cancellation_permitted:
            description: Whether this product may be cancelled online by customers. A value of `unpaid` means this product may be cancelled only if no payments have been recorded against the order it is part of.
            $ref: '#/components/schemas/customerCancellationPermitted'
          customer_cancellation_min_duration:
            type: string
            description: The minimum duration that must be left before the booking this product is a part of in order for the customer to cancel, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P7D
          updated_at:
            type: string
            format: date-time
            description: The time and date that the product was last updated.
          deleted_at:
            type: string
            format: date-time
            description: The time and date that the product was archived.
            nullable: true
          brand_id:
            type: string
            format: uuid
            description: The brand ID of the product.
            nullable: true
        required:
          - id
          - name
          - currency
          - description
          - external_id
          - product_code
          - price_from
          - price_to
          - standard_price
          - barcode
          - inventory_product_id
          - image
          - offered_online
          - private
          - site_id
          - tag_ids
          - tags
          - category_ids
          - categories
          - price_rules
          - revenue_centre
          - updated_at
          - deleted_at
  - name: Refunds
    description: |
      A `Refund` is a single return of funds against a `Payment` — the
      record of money sent back to a customer for a paid-for purchase.

      Refunds are always created against a `Payment` on an `Order`, so
      the operations that produce and list them live in the
      [Orders](/endpoints/Orders) section, alongside the rest of the
      order lifecycle. This page is the canonical reference for the
      `Refund` object's shape — what fields you'll see on a
      `refund.complete` webhook, on a list-order-refunds response, or
      embedded under `payments[].refunds[]` on an order detail view.

      The most-used flow is `actionRefundOrderPayment` (kick off a
      refund against a specific payment) → `refund.complete` webhook
      (delivery-side confirmation). For partial refunds and
      refund-eligibility checks, see
      [`getOrderRefundableItems`](/endpoints/Orders#getOrderRefundableItems).
    x-info:
      baseSchema:
        title: Refund
        description: An instance of a refund.
        type: object
        additionalProperties: false
        properties:
          id:
            description: The ID of the refund.
            type: string
            format: object-id
          payment_id:
            description: The ID of the payment that was refunded.
            type: string
            format: object-id
          amount:
            description: The amount of the refund.
            type: integer
            format: integer
          currency:
            $ref: '#/components/schemas/properties_currency'
          notes:
            description: Notes that were added against the refund.
            type: string
            nullable: true
          status:
            description: The current status of the refund.
            type: string
            enum:
              - pending
              - complete
              - failed
          processor_data:
            description: A dictionary of processor-specific data.
            type: object
            additionalProperties: true
          created_at:
            description: The date and time that the refund was created.
            type: string
            format: date-time
        required:
          - id
          - payment_id
          - amount
          - currency
          - status
          - created_at
          - processor_data
  - name: Reports
    description: |
      The `Reports` group of endpoints provide access to various reports on the Trybe platform.
  - name: ResDiaryIntegration
    description: Manage a site's integration with ResDiary.
  - name: RevenueByCentre
    description: The revenue by centre report provides a summary of revenue by reporting centre.
  - name: RevenueCentres
    description: |
      A revenue centre is an accounting category against which revenues should be recorded.
  - name: RoomTags
    description: |
      A `RoomTag` is a free-form label that can be attached to one or
      more `Room`s within an organisation. Tags are used to group
      rooms for reporting and to assign appointment types to a pool
      of equivalently-equipped rooms.
  - name: Rooms
    description: |
      A `Room` is a physical space in which appointments are
      delivered. Rooms have a capacity, an optional custom
      availability schedule, and tags that drive allocation when an
      appointment is booked.
    x-info:
      baseSchema:
        title: Room
        description: |
          A `Room` is a physical space in which appointments are delivered.
          Rooms have capacity (1 = single occupancy, >1 = multi-guest), an
          availability schedule, and optional tags / zones. They power room
          allocation when an appointment is booked: the availability engine
          picks an unoccupied room whose capacity, tags, and zones match the
          appointment type.
        type: object
        additionalProperties: false
        required:
          - id
          - organisation_id
          - site_id
          - name
          - capacity
          - availability_rules
          - suitable_for_tags
          - tag_ids
        properties:
          id:
            type: string
            format: object-id
            description: Unique identifier of the room.
            example: 5dcb47800000000000000000
          organisation_id:
            type: string
            format: uuid
            description: ID of the organisation the room belongs to.
            example: 0193b6e0-3b56-7000-9f50-9d3d5e2c1111
          site_id:
            type: string
            format: uuid
            description: ID of the site the room belongs to. A room is scoped to exactly one site.
            example: 0193b6e0-3b56-7000-9f50-9d3d5e2c2222
          name:
            type: string
            description: |
              Display name for the room. Visible to staff in the calendar and
              admin UI; not shown to customers.
            example: Treatment Room 1
          capacity:
            type: integer
            minimum: 1
            description: |
              How many concurrent bookings the room can host. `1` means
              single-occupancy (appointments exclusively block the room);
              values > 1 enable multi-guest sharing when the appointment
              type opts in via `allocate_multi_capacity_rooms`.
            example: 1
          availability_rules:
            type: array
            description: |
              Per-day availability windows that override the site's opening
              hours for this room. Empty array means the room follows site
              opening hours.
            items:
              $ref: '#/components/schemas/AvailabilityRule'
          suitable_for_tags:
            type: array
            description: |
              Tag IDs that this room is suitable for. The availability
              engine matches these against the booking's required tags to
              decide if the room can host the appointment (e.g. a "wet
              room" tag for hydrotherapy treatments).
            items:
              type: string
              format: object-id
          tag_ids:
            type: array
            description: |
              Free-form tag IDs attached to the room for reporting and
              filtering. Distinct from `suitable_for_tags` — these don't
              affect allocation logic.
            items:
              type: string
              format: object-id
          tags:
            type: array
            description: Hydrated `Tag` records for the room's `tag_ids`.
            items:
              $ref: '#/components/schemas/Tag'
          zones:
            type: array
            description: |
              Hydrated `Zone` records this room belongs to. Zones group
              rooms in the floor plan and are used for spatial constraints
              in availability.
            items:
              $ref: '#/components/schemas/Zone'
  - name: SchedulingIssues
    description: |
      A `SchedulingIssue` flags an attention-needed problem with an existing booking — a practitioner double-booked, a rota change that no longer fits the schedule, etc. Generated by the scheduling engine and managed by admin staff.
  - name: SecurityPolicies
    description: |
      Organisation-wide security policies that govern how all
      site-users in an organisation authenticate. Today this covers
      the two-factor enforcement flag (`/2fa-enforcement-policy`)
      and the password expiry interval (`/password-expiry-policy`).
      Reading any policy requires the `settings:view` permission;
      changing one requires `org-users:manage`.
  - name: SessionBookings
    description: |
      A `SessionBooking` records a customer's attendance against a
      specific session occurrence — captures check-in, no-show, intake
      form status and arrival stage so reception staff can manage
      walk-in flow.
    x-info:
      baseSchema:
        title: SessionBooking
        description: Describes a booking for a session.
        type: object
        additionalProperties: false
        required:
          - id
          - checked_in_at
          - checked_out_at
          - customer_id
          - email
          - first_name
          - guests
          - intake_form_required
          - intake_forms_completed
          - is_no_show
          - last_name
          - order_id
          - order_item_id
          - order_ref
          - organisation_id
          - phone
          - session_id
          - session_type_id
          - session_type_name
          - site_id
          - stage
          - status
          - created_at
          - updated_at
        properties:
          id:
            type: string
            description: The ID of the session.
            example: 5dcb47800000000000000000
          checked_in_at:
            type: string
            format: date-time
            nullable: true
            description: The time this booking was checked in.
            example: '2022-03-02T09:00:00+00:00'
          checked_out_at:
            type: string
            format: date-time
            nullable: true
            description: The time this booking was checked out.
            example: '2022-03-02T10:00:00+00:00'
          customer_id:
            type: string
            description: The ID of the customer this booking is for.
            example: 5dcb47800000000000000020
          email:
            type: string
            description: The email address of the customer.
            example: janedoe@example.com
          first_name:
            type: string
            description: The first name of the customer.
            example: Jane
          guests:
            type: array
            items:
              $ref: '#/components/schemas/Guest'
          intake_forms_completed:
            type: boolean
            description: Whether the required intake form has been completed.
            example: false
          intake_form_required:
            type: boolean
            description: Whether the session booking requires an intake form to be completed.
            example: true
          is_no_show:
            type: boolean
            description: Whether this booking was marked as a no-show.
          last_name:
            type: string
            description: The last name of the customer.
            example: Doe
          order_id:
            type: string
            description: The ID of the order associated with this session.
            example: 5dcb47800000000000000009
          order_item_id:
            type: string
            description: The ID of the order item associated with this session.
            example: 5dcb47800000000000000019
          order_ref:
            type: string
            description: The order reference associated with this session.
            example: TRY00
          organisation_id:
            type: string
            description: The ID of the organisation the session booking belongs to.
            example: 00000000-0000-0000-0000-000000000000
          phone:
            type: string
            description: The customer's phone number.
            example: '+447727123456'
          session_id:
            type: string
            description: The ID of the session this booking is for.
            example: 5dcb47800000000000001111
          session_type_id:
            type: string
            description: The ID of the session type.
            example: 5dcb47800000000000001234
          session_type_name:
            type: string
            description: The name of the session type.
            example: Spa access
          site_id:
            type: string
            description: The ID of the site the session booking belongs to.
            example: 00000000-0000-0000-0000-111111111111
          stage:
            type: string
            description: The current stage of the order the session belongs to.
            enum:
              - not_arrived
              - arrived
              - in_treatment
              - checked_out
          status:
            type: string
            description: The status of the booking.
            example: none
            enum:
              - new
              - in_progress
              - confirmed
              - waitlisted
          created_at:
            $ref: '#/components/schemas/CreatedAt'
          updated_at:
            $ref: '#/components/schemas/UpdatedAt'
  - name: SessionRecurrenceGroups
    description: A `SessionRecurrenceGroup` represents the recurrence of sessions for a `SessionType`.
    x-info:
      baseSchema:
        title: SessionRecurrenceGroup
        type: object
        description: A `SessionRecurrenceGroup` object
        additionalProperties: false
        required:
          - capacity
          - deleted_at
          - id
          - name
          - recurrence_end
          - recurrence_start
          - room
          - session_type_id
          - start_time
          - start_times
          - weekdays
        properties:
          capacity:
            type: integer
            description: The capacity of each session in this group.
            example: 12
          deleted_at:
            type: string
            format: date-time
            nullable: true
            description: A timestamp of when the this was deleted.
          id:
            type: string
            format: object-id
            description: The ID of the recurrence group.
            example: 609bd745e4358066f7061d82
          name:
            type: string
            description: An option name for the recurrence group.
            example: Mondays with Adrienne
          practitioner:
            description: The practitioner who leads the sessions in this group.
            $ref: '#/components/schemas/PractitionerSummary'
          recurrence_end:
            type: string
            nullable: true
            format: date
            description: The end date of the recurrence group.
            example: '2021-05-10'
          recurrence_start:
            type: string
            nullable: true
            format: date
            description: The start date of the recurrence group.
            example: '2021-04-10'
          room:
            description: The room where the sessions in this group take place.
            $ref: '#/components/schemas/RoomSummary'
          session_type_id:
            description: The ID of the `SessionType` this `SessionRecurrenceGroup` belongs to.
            type: string
            format: object-id
          start_time:
            type: string
            nullable: true
            description: The start time of each occurrence, in 24 hour format
            example: '16:00'
            deprecated: true
          start_times:
            type: array
            minItems: 1
            description: An array of start times
            items:
              type: object
              title: StartTime
              additionalProperties: false
              required:
                - id
                - value
              properties:
                id:
                  type: string
                  format: object-id
                  description: The ID of the start time
                value:
                  type: string
                  description: The start time of each occurrence, in 24 hour format
                  example: '16:00'
          weekdays:
            type: array
            description: The weekdays this rule applies to
            items:
              type: string
              example: monday
  - name: SessionTypes
    description: A `SessionType` represents a type of session that can be booked at a site.
    x-info:
      baseSchema:
        title: SessionType
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: |
              Unique identifier of the session type. Returned from
              `createSessionType`; used to look up the type, manage its
              recurrence groups, set up bookings, and copy it.
          name:
            type: string
            description: The name of this session type
            example: Vinyasa yoga
          description:
            type: string
            description: A description of the session type
            example: A dynamic form of yoga
          product_code:
            type: string
            description: A custom product code for the session type.
            example: MAS123
          currency:
            $ref: '#/components/schemas/Currency'
          external_id:
            type: string
            nullable: true
            description: An external identifier for this offering, used by integrations to map this `SessionType` to an external system.
            example: ext-yoga-vinyasa
          hidden_on_schedule:
            type: boolean
            description: |
              When true, this session type is excluded from the staff
              schedule view in the admin UI even though sessions are still
              visible to customers and bookable. Used to keep operational
              sessions (e.g. private member-only programmes) off the main
              calendar without making them unbookable.
            example: false
          image_id:
            type: string
            nullable: true
            format: uuid
            description: |
              Media ID of the hero image for the session type, shown on the
              storefront listing and detail page. Upload via
              [`createMedia`](/endpoints/Media#createMedia) first and pass
              the returned ID here. Pass `null` to remove the image.
          image:
            $ref: '#/components/schemas/Media'
          offered_online:
            type: boolean
            description: Whether this session type is bookable online
          private:
            type: boolean
            description: Whether this is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
          site_id:
            type: string
            format: uuid
            description: |
              Identifier of the site this session type is published at.
              Session types are scoped per site so each venue can run its
              own programme; the type's bookings, capacity, and pricing
              are managed against this site.
          duration:
            type: integer
            example: 60
            description: The duration of the session type.
          max_baskets_per_session:
            type: integer
            example: 1
            description: Limit the number of baskets that may create bookings for a single session.
          max_advance_bookings_interval:
            type: string
            description: The maximum time before a session's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P2W
          min_advance_bookings_interval:
            type: string
            description: The minimum time before a session's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P2D
          customers_only:
            type: boolean
            description: Whether this session requires the customer to be logged in to book.
            example: false
          members_only:
            type: boolean
            description: Whether this session requires an active membership in order to book.
            example: true
          max_bookings_per_member:
            type: integer
            description: The maximum number of bookings a member may make on a single session.
            example: 1
          permitted_membership_type_ids:
            type: array
            description: |
              If this session is for members only, this property may be used to restrict the offering further
              so it may only be booked by active members with of one of the given membership types.
            items:
              type: string
          membership_booking_windows_enabled:
            type: boolean
            description: Whether membership-specific booking windows should be enabled for this session type.
            example: true
          membership_booking_windows:
            type: array
            items:
              $ref: '#/components/schemas/MembershipBookingWindow'
          customer_cancellation_permitted:
            description: Whether bookings of this type may be cancelled online by customers. A value of `unpaid` means this booking my be cancelled only if no payments have been recorded against the order it is part of.
            $ref: '#/components/schemas/customerCancellationPermitted'
          customer_cancellation_min_duration:
            type: string
            description: The minimum duration that must be left before the booking in order for the customer to cancel, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P7D
          customer_reschedule_permitted:
            description: Whether bookings of this type may be rescheduled online by customers. A value of `unpaid` means this booking may be rescheduled only if no payments have been recorded against the order it is part of.
            $ref: '#/components/schemas/customerReschedulePermitted'
          customer_reschedule_min_duration:
            type: string
            description: The minimum duration that must be left before the booking in order for the customer to reschedule, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P7D
          waitlist_enabled:
            type: boolean
            example: true
            description: Whether the waitlist is enabled for sessions of this type.
          max_waitlist_size:
            type: integer
            nullable: true
            description: The maximum number of customers allowed on the waitlist for sessions of this type. Null means the waitlist is unlimited.
            example: 10
          min_guests:
            type: integer
            description: The minimum guests allowed in a booking for this session
            example: 1
          max_guests:
            type: integer
            description: The maximum guests allowed in a booking for this session
            example: 2
          max_per_basket:
            type: integer
            nullable: true
            description: |
              Maximum number of times this session type can appear in a
              single basket. Null = unlimited. Use to throttle blanket
              bookings of capacity-constrained sessions.
            example: 4
          max_per_guest:
            type: integer
            nullable: true
            description: |
              Maximum number of times this session type can be assigned to
              a single guest within a basket. Null = unlimited. Defends
              against accidental duplicate bookings of the same guest.
            example: 2
          price_rules:
            type: array
            description: The rules defining prices for this session type.
            items:
              $ref: '#/components/schemas/SessionPriceRule'
          yield_management:
            $ref: '#/components/schemas/YieldManagement'
          standard_price:
            type: integer
            nullable: true
            description: |
              The standard price for this session type, in the smallest
              currency unit (e.g. pence). `null` if a standard price hasn't
              been configured — this is distinct from a price of zero.
            example: 5000
          category_ids:
            description: The category IDs associated with this session type
            type: array
            items:
              type: string
          categories:
            description: The category associated with this session type
            type: array
            items:
              $ref: '#/components/schemas/schemas_Category-2'
          recurrence_groups:
            description: An array of recurrence groups for this session type
            deprecated: true
            type: array
            items:
              $ref: '#/components/schemas/SessionRecurrenceGroup'
          meta:
            title: Meta
            type: object
            additionalProperties: false
            properties:
              title:
                type: string
                nullable: true
                description: The meta title of this offering. If not specified, it falls back to the name of the offering.
              description:
                type: string
                nullable: true
                description: The meta description of this offering. If not specified, it falls back to the description of the offering.
          upsell_offerings:
            type: array
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          cross_sell_offerings:
            type: array
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          related_retail_offerings:
            type: array
            items:
              $ref: '#/components/schemas/OfferingIdentifier'
          revenue_centre:
            type: string
            description: The revenue centre to assign revenue to for this offering
            example: spa
          include_pricing_on_calendar:
            type: boolean
            description: Whether the booking engine calendar should display pricing under each date
          visibility:
            type: string
            description: |
              Visibility on the shopfront. `public` = listed in search and
              browse; `link_only` = bookable only via direct link (excluded
              from search/browse); `private` = admin-only, never offered to
              customers.
            example: public
            enum:
              - link_only
              - private
              - public
          updated_at:
            type: string
            format: date-time
            description: The time and date that the appointment type was last updated.
            example: '2020-02-24T12:00:00+01:00'
          deleted_at:
            type: string
            nullable: true
            format: date-time
            description: The time and date that the appointment type was archived.
            example: '2020-02-24T12:00:00+01:00'
        required:
          - id
          - name
          - description
          - product_code
          - currency
          - external_id
          - image_id
          - offered_online
          - private
          - site_id
          - duration
          - max_baskets_per_session
          - max_advance_bookings_interval
          - min_advance_bookings_interval
          - members_only
          - max_bookings_per_member
          - membership_booking_windows_enabled
          - membership_booking_windows
          - customer_cancellation_permitted
          - customer_cancellation_min_duration
          - customer_reschedule_permitted
          - customer_reschedule_min_duration
          - waitlist_enabled
          - max_waitlist_size
          - min_guests
          - max_guests
          - max_per_basket
          - max_per_guest
          - price_rules
          - standard_price
          - yield_management
          - category_ids
          - categories
          - meta
          - upsell_offerings
          - cross_sell_offerings
          - related_retail_offerings
          - revenue_centre
          - include_pricing_on_calendar
          - visibility
          - updated_at
          - deleted_at
  - name: Sessions
    description: A `Session` represents an occurrence of a `SessionType`.
  - name: SevenRoomsIntegration
    description: Manage a site's integration with SevenRooms.
  - name: Shop
    description: Shopfront endpoints.
  - name: SignupTokens
    description: |
      A `SignupToken` permits a customer to sign up for a private `MembershipType` or
      non-default `MembershipRate`. Tokens cap how many signups they can be used for and
      can pre-populate customer details (name and email).
    x-info:
      baseSchema:
        title: SignupToken
        type: object
        additionalProperties: false
        description: |
          A `SignupToken` permits a customer to sign up for a private `MembershipType` or
          non-default `MembershipRate`. Tokens carry an optional cap on how many times they can
          be used and can pre-populate customer details such as name and email.
        properties:
          id:
            type: string
            description: The ID of the signup token.
            example: 000000-000000-000000-000000
          membership_type_id:
            type: string
            description: The MembershipType this token allows signups as
            example: 000000-000000-000000-000000
          membership_rate_id:
            type: string
            description: The MembershipRate this token allows signups as. If omitted, the default rate of the given type will be used.
            example: 000000-000000-000000-000000
            nullable: true
          start_date:
            type: string
            description: The date which the membership should start
            format: date
            example: '2021-02-21'
            nullable: true
          end_date:
            type: string
            description: The date which the membership should end
            format: date
            example: '2022-02-21'
            nullable: true
          duration:
            type: string
            description: The duration of the membership as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P1M
          max_uses:
            type: integer
            nullable: true
            description: |
              The maximum number of times this signup token can be used. If null, it can be used an
              unlimited number of times. When the number of uses reaches the max_uses, it is soft-deleted.
          uses:
            type: integer
            description: The number of times this signup token has been used.
          first_name:
            type: string
            description: The first name of the customer this token allows signups as. If omitted, the customer can set a first name.
            nullable: true
            example: Dan
          last_name:
            type: string
            description: The last name of the customer this token allows signups as. If omitted, the customer can set a last name.
            nullable: true
          email:
            type: string
            description: The email of the customer this token allows signups as. If omitted, the customer can set an email.
            example: dan@try.be
            nullable: true
        required:
          - id
          - membership_type_id
          - membership_rate_id
          - start_date
          - end_date
          - max_uses
          - uses
  - name: Sites
    description: |
      A `Site` represents a property using Trybe.
    x-info:
      baseSchema:
        type: object
        title: Site
        description: A physical or virtual venue under a `Brand` — typically a single spa, club, or location. Sites own their own offerings, sessions, pricing and staff, and are the unit at which API keys are scoped. A user must be granted access to a site individually before they can act on its data.
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the site
          billing_customer_id:
            type: string
          brand_id:
            type: string
            format: uuid
            description: The ID of the `Brand` the `Site` belongs to.
          brand_name:
            type: string
            description: The name of the `Brand` the `Site` belongs to.
          country_code:
            type: string
            description: The country code of the site
            example: GB
            nullable: true
          created_at:
            type: string
            format: date-time
            description: The date and time that the site was created
          onboarding_completed_at:
            type: string
            format: date-time
            nullable: true
            description: The date and time that the site's onboarding was completed
          currency:
            type: string
            description: The currency of the site. See [Supported Currencies](/endpoints/Meta#listMetaSupportedCurrencies) for a list of supported currencies.
            example: GBP
          external_id:
            type: string
            description: |
              An external ID for the site
              This can be used to link the site to an external system.
            nullable: true
            example: ext-site-london-bridge
          frontend_subdomain:
            type: string
            description: The subdomain of the site's frontend
            example: palmtreespa
          is_read_only:
            type: boolean
            description: Are billing details read-only.
          locale:
            type: string
            description: The locale of the site. See [Supported Locales](/endpoints/Meta#listMetaSupportedLocales) for a list of supported locales.
            example: en
          name:
            type: string
            description: |
              Display name of the site. Shown to customers in the storefront,
              in the admin UI, on receipts, and on communications. Trimmed;
              1-120 characters, must not contain HTML.
            example: Palm Tree Spa
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation that the site belongs to
          organisation_name:
            type: string
            description: The name of the organisation that the site belongs to
            example: Palm Tree Holdings Ltd.
          property_type:
            type: string
            description: The type of property the site is.
            enum:
              - Spa & Leisure Hotel
              - Spa Hotel
              - Spa Hotel & Golf
              - Standalone Leisure
              - Standalone Spa
              - Other
            default: Spa & Leisure Hotel
            example: Spa & Leisure Hotel
          timezone:
            type: string
            nullable: true
            description: The site's local timezone as an IANA zone identifier (e.g. `Europe/London`, `America/New_York`). All schedule, opening hours and reporting figures are interpreted in this zone, and the value is used to convert UTC timestamps in API responses into local times for display.
            example: Europe/London
        required:
          - id
          - billing_customer_id
          - brand_id
          - brand_name
          - country_code
          - created_at
          - currency
          - external_id
          - frontend_subdomain
          - is_read_only
          - locale
          - name
          - onboarding_completed_at
          - organisation_id
          - organisation_name
          - property_type
          - timezone
  - name: SmsFragments
    description: |
      An `SmsFragment` is a template for an SMS message.
  - name: SmsUsage
    description: |
      The `SmsUsage` report lists out sent SMS messages by site.
  - name: StockAdjustments
    description: |
      The `StockAdjustments` report lists out stock adjustments for a site.
  - name: StockOnHand
    description: |
      The `StockOnHand` report lists out the stock on hand for a site.
  - name: StockTakes
    description: |
      A `StockTake` represents a stock take of inventory items.
    x-info:
      baseSchema:
        title: StockTake
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the stocktake.
          description:
            type: string
            description: The description of the stocktake.
            example: Stocktake started on 01/06/2024
          status:
            type: string
            description: The status of the stocktake.
            enum:
              - in_progress
              - complete
          currency:
            type: string
            description: The currency of the stocktake.
            example: gbp
          created_by_id:
            type: string
            format: uuid
            description: The ID of the user who created the stocktake.
            nullable: true
          created_by:
            type: object
            description: The summary of the user who created the stocktake.
            $ref: '#/components/schemas/schemas_UserSummary'
            nullable: true
          posted_by_id:
            type: string
            format: uuid
            description: The ID of the user who posted the stocktake.
            nullable: true
          posted_by:
            type: object
            description: The summary of the user who posted the stocktake.
            $ref: '#/components/schemas/schemas_UserSummary'
            nullable: true
          items_added:
            type: boolean
            description: Whether items have been added to the stock take.
          site_id:
            type: string
            format: uuid
            description: The ID of the site the stocktake belongs to.
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation this stocktake belongs to.
          created_at:
            type: string
            format: date-time
            description: The date and time the stocktake was created.
            example: '2024-06-01T12:00:00Z'
          posted_at:
            type: string
            format: date-time
            description: The date and time the stocktake was posted.
            nullable: true
          updated_at:
            type: string
            format: date-time
            description: The date and time the stocktake was last updated.
        required:
          - id
          - description
          - status
          - currency
          - created_by_id
          - items_added
          - site_id
          - organisation_id
          - created_at
          - posted_at
          - updated_at
  - name: Subscriptions
    description: |
      A `Subscription` represents the authenticated user's opt-in to receive notifications
      (e.g. failed payment, expiring membership) for a specific `Site`.
    x-info:
      baseSchema:
        title: Subscription
        type: object
        additionalProperties: false
        description: |
          A `Subscription` represents the authenticated user's opt-in to receive a particular
          notification (e.g. `failed_payments`, `expiring_soon`) for a specific `Site`.
        properties:
          id:
            type: string
            format: uuid
            description: The ID of the subscription
          site_id:
            type: string
            format: uuid
            description: The site ID which this subscription relates to
          notification_type:
            type: string
            description: The type of notification this subscription is for
            enum:
              - failed_payments
              - expiring_soon
              - new_signups
              - revoked_mandate
          created_at:
            type: string
            format: date-time
            description: The date-time when this subscription was created
          updated_at:
            type: string
            format: date-time
            description: The date-time when this subscription was last updated
        required:
          - id
          - site_id
          - notification_type
          - created_at
          - updated_at
  - name: Sudo
    description: |
      Endpoints for elevating the current session to perform
      sensitive actions. Calls require the user to re-prove identity
      (typically by re-entering their password) and return a short-
      lived cookie that authorises follow-up operations.
  - name: Suppliers
    description: |
      A `Supplier` represents a supplier of goods to an organisation.
  - name: TableReservationTypes
    description: Endpoints to manage table reservation types.
    x-info:
      baseSchema:
        title: TableReservationType
        description: A bookable category of table reservation (e.g. "Dinner", "Brunch", "Cabana"). The type owns the configurable options (party size, duration, deposit) that the storefront presents to a guest and which subsequent reservations inherit. Soft-deleted types can be restored via the `/restore` endpoint.
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: |
              Stable identifier for the table reservation type. Used by
              the storefront to fetch options and availability, and by
              reservations to record which type a guest booked into. Safe
              to expose to end users.
            example: 5dcb47800000000000000010
          name:
            type: string
            description: |
              Guest-facing display name for the reservation type. Shown on
              the storefront alongside the type's description and image.
              Keep concise — typically 1-3 words such as `Main restaurant`
              or `Sunday brunch`.
            example: Main restaurant
          integration_config:
            $ref: '#/components/schemas/IntegrationConfig'
            nullable: true
          description:
            type: string
            nullable: true
            description: A description of the table reservation type.
            example: Enjoy a relaxing meal in our main restaurant.
          external_id:
            type: string
            nullable: true
            description: An external identifier for this offering.
            example: resdiary:12345
          product_code:
            type: string
            nullable: true
            description: A custom product code for the table reservation type.
            example: DIN
          image:
            $ref: '#/components/schemas/Media'
          revenue_centre:
            type: string
            nullable: true
            description: The revenue centre to assign revenue to for this offering
            example: restaurant
          options:
            type: array
            items:
              $ref: '#/components/schemas/schemas_TableReservationOption'
          customer_reschedule_permitted:
            description: Whether bookings of this type may be rescheduled online by customers. A value of `unpaid` means this booking may be rescheduled only if no payments have been recorded against the order it is part of.
            $ref: '#/components/schemas/customerReschedulePermitted'
          customer_reschedule_min_duration:
            type: string
            nullable: true
            description: The minimum duration that must be left before the booking in order for the customer to reschedule, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            example: P7D
        required:
          - id
          - name
          - integration_config
          - description
          - external_id
          - product_code
          - revenue_centre
          - options
          - customer_reschedule_permitted
          - customer_reschedule_min_duration
  - name: TaxConfigurations
    description: |
      A tax configuration is one or more 'sets' of taxes that should apply to a the sale of a single item.
  - name: TeiIntegration
    description: Manage a site's integration with TEI.
  - name: TerminalRequests
    description: |
      A `TerminalRequest` represents a request to a terminal, such as a payment request or a wearable association.
  - name: TerminalTokenisations
    description: |
      A `TerminalTokenisation` represents a tokenisation request to a terminal.
  - name: TwilioProvisioning
    description: |
      Manage Twilio phone number provisioning for sites. Handles regulatory bundle creation,
      approval tracking, and number purchasing.
  - name: Users
    description: |
      A `User` represents a user of the Trybe platform.
  - name: VisitType
    description: |
      A `VisitType` represents a configuration for a `Visit`.
  - name: Visits
    description: |
      A `Visit` represents a customer's visit to a site.
  - name: VoucherCodes
    description: |
      A `VoucherCode` is a single issued instance of a `VoucherType` —
      the redeemable code, its monetary balance, validity dates,
      recipient, and delivery metadata. `VoucherCode`s are produced
      by the basket pipeline when a voucher is purchased and consumed
      when the code is presented as payment against a future order.
  - name: VoucherDeliveryOption
    description: |
      A `VoucherDeliveryOption` represents a method of delivering a voucher to a customer.
  - name: VoucherLedger
    description: |
      A report detailing voucher revenue balances.
  - name: VoucherPurchases
    description: |
      A `VoucherPurchase` is the purchase-side record of a voucher
      transaction — it captures the buyer, the recipient's contact
      details, the delivery method, and the gift-email content. The
      tradable `VoucherCode`s issued by the purchase are managed under
      the `VoucherCodes` tag.
  - name: VoucherTypes
    description: |
      A `VoucherType` represents a type of voucher that can be purchased at a site.
  - name: Vouchers
    description: |
      A `Voucher` is the catalogue-level record for a third-party gift
      voucher (e.g. one imported from GiftPro) that has been synced into
      Trybe and made redeemable at a site. `Voucher`s are managed via
      these endpoints — import the latest catalogue, list the synced
      records, fetch a single voucher, tweak its redemption rules, look
      up a redemption code at point of sale, or add/remove individual
      offerings on the allowlist. Trybe-native voucher products that are
      sold through the basket use `VoucherType` instead.
    x-info:
      baseSchema:
        title: Voucher
        description: |
          A `Voucher` is the catalogue-level record for a third-party gift
          voucher (e.g. a GiftPro voucher) that has been imported into Trybe
          and made redeemable at a site. Each `Voucher` represents one product
          in the external system — its name, monetary value, currency, and the
          rules constraining where it may be redeemed (allowed offerings,
          permitted weekdays, blackout date sets).

          `Voucher`s are distinct from `VoucherType`s: a `VoucherType` is a
          Trybe-native voucher product that can be sold through the basket and
          issues `VoucherCode`s on purchase; a `Voucher` is an external,
          pre-issued product whose redemption is brokered through a
          `VoucherIntegration` (e.g. GiftPro). The two share a similar runtime
          redemption flow but are managed via separate endpoints.
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: object-id
            description: The Trybe ID of the voucher record.
            example: 65f0a1b2c3d4e5f6a7b8c9d0
          name:
            type: string
            description: |
              Customer- and cashier-facing name of the voucher, mirrored from
              the source system at import time.
            example: Twilight Spa Day Gift Voucher
          description:
            type: string
            nullable: true
            description: |
              Long-form description of the voucher imported from the source
              system. Shown to cashiers when redeeming.
            example: A 90-minute treatment, lunch, and full access to the spa facilities.
          processor_voucher_id:
            type: string
            description: |
              The voucher's primary key in the external processor's system
              (e.g. the GiftPro voucher ID). Used to reconcile the Trybe
              record with the source of truth.
            example: gp_8421
          price:
            type: integer
            description: |
              The face value of the voucher in the smallest unit of
              `currency` (e.g. pence for `gbp`). Mirrored from the source
              system and used as the redemption amount when the voucher is
              presented as payment.
            example: 12500
          currency:
            type: string
            description: |
              The ISO-4217 currency code (lowercase) the voucher's `price` is
              expressed in.
            example: gbp
          processor:
            type: string
            description: |
              Identifier of the integration that owns this voucher. Drives
              which redemption flow Trybe routes the voucher through at
              checkout.
            example: giftpro
          processor_data:
            type: object
            description: |
              Processor-specific metadata captured at import time. Shape
              varies by `processor`; treat as opaque unless you specifically
              target a known integration.
            additionalProperties: true
            example: {}
          valid_offerings:
            type: array
            description: |
              Offerings the voucher may be redeemed against. When the
              endpoint is called with offering summaries enabled (the default
              for `getVoucher` and the mutation endpoints), each entry is
              enriched with the offering's display name. When empty, the
              voucher is redeemable against any offering subject to the
              site's normal rules.
            items:
              $ref: '#/components/schemas/VoucherValidOffering'
          valid_weekdays:
            type: array
            description: |
              Lowercase weekday names the voucher may be redeemed on. Empty
              means "any weekday".
            items:
              type: string
              enum:
                - monday
                - tuesday
                - wednesday
                - thursday
                - friday
                - saturday
                - sunday
            example:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
          invalid_date_set_ids:
            type: array
            description: |
              IDs of date sets (e.g. bank holidays, peak-season blackouts) on
              which the voucher may **not** be redeemed. Each ID must
              reference a date set on the caller's organisation.
            items:
              type: string
              format: object-id
            example:
              - 65f0a1b2c3d4e5f6a7b8c9aa
          site_id:
            type: string
            format: uuid
            description: The ID of the site this voucher record belongs to.
            example: 1f3c0e2a-9b8d-4c5e-a6f7-1234567890ab
          organisation_id:
            type: string
            format: uuid
            description: The ID of the organisation that owns the voucher record.
            example: 0a1b2c3d-4e5f-6789-abcd-ef0123456789
          processor_created_at:
            type: string
            format: date-time
            nullable: true
            description: When the voucher was created in the source processor's system.
            example: '2025-12-15T09:30:00+00:00'
          created_at:
            type: string
            format: date-time
            description: When the voucher record was imported into Trybe.
            example: '2026-01-04T11:00:00+00:00'
          updated_at:
            type: string
            format: date-time
            description: When the voucher record was last updated in Trybe.
            example: '2026-04-22T14:18:00+00:00'
        required:
          - id
          - name
          - description
          - processor_voucher_id
          - price
          - currency
          - processor
          - processor_data
          - valid_offerings
          - valid_weekdays
          - invalid_date_set_ids
          - site_id
          - organisation_id
          - processor_created_at
          - created_at
          - updated_at
  - name: WebhookCalls
    description: Endpoints to view webhook calls made by Trybe
  - name: WebhookConfig
    description: Endpoints to manage config relating to webhooks sent from Trybe
  - name: YieldInsights
    description: |
      Aggregated occupancy and revenue insights for a site's yield
      pricing — where the peak and quiet spells are, and what yield
      rules have earned since they were switched on.
    x-info:
      baseSchema:
        title: YieldInsights
        description: |
          A site-level summary of how yield pricing is set up and performing
          over a recent reporting period. The state flags
          (`has_occupancy_data`, `is_yield_enabled`, `opportunities.has_data`,
          `performance.has_data`) are always present; the stat fields inside
          `opportunities` and `performance` are `null` until the underlying
          calculation has data to work from.
        type: object
        additionalProperties: false
        properties:
          period:
            type: string
            description: The reporting period the insights were calculated over.
            enum:
              - last_30_days
              - last_60_days
              - last_90_days
            example: last_30_days
          window:
            $ref: '#/components/schemas/YieldInsightsWindow'
          currency:
            type: string
            description: |
              The ISO-4217 currency code every monetary amount in this
              response (`performance.additional_revenue`,
              `performance.aov_uplift_amount`) is denominated in. The amounts
              themselves are integers in this currency's minor units.
            example: GBP
          has_occupancy_data:
            type: boolean
            description: |
              Whether the site has any occupancy data at all. When `false`
              there is nothing to calculate insights from, so the stat fields
              elsewhere in the response are `null`.
            example: true
          is_yield_enabled:
            type: boolean
            description: |
              Whether yield pricing is switched on for the site. When `false`
              the `performance` stats have nothing to measure and are `null`.
            example: true
          opportunities:
            $ref: '#/components/schemas/YieldInsightsOpportunities'
          performance:
            $ref: '#/components/schemas/YieldInsightsPerformance'
        required:
          - period
          - window
          - currency
          - has_occupancy_data
          - is_yield_enabled
          - opportunities
          - performance
  - name: YieldRules
    description: |
      A `YieldRule` adjusts an offering's price according to how busy the site
      is, on top of the offering's existing price rules and within its yield
      price guardrails.
    x-info:
      baseSchema:
        title: YieldRule
        description: |
          A demand-based price adjustment configured for a single offering.

          Adjustments apply on top of the offering's existing price rules, and are
          bounded by its yield price guardrails. Rules are per-offering: applying one
          to several offerings at once creates an independent rule for each, so
          editing one never affects the others.
        type: object
        additionalProperties: false
        properties:
          id:
            type: string
            format: uuid
          offering_type:
            $ref: '#/components/schemas/offeringType'
          offering_id:
            type: string
            format: uuid
            description: The offering this rule adjusts the price of.
          site_id:
            type: string
            format: uuid
          created_batch_id:
            type: string
            format: uuid
            nullable: true
            description: |
              Shared by every rule created in the same request. The rules remain
              independent of one another — editing one does not affect the others — so
              this only records that they were created together.
          weekdays:
            type: array
            description: The days of the week this rule applies on.
            items:
              $ref: '#/components/schemas/weekday'
          time_from:
            type: string
            nullable: true
            description: |
              Start of the daily window this rule applies within, in the site's local
              time. 24-hour `HH:MM`. Each selected weekday is the day its window
              starts on. Null alongside a null `time_to` means the rule applies all
              day.
            example: '12:00'
          time_to:
            type: string
            nullable: true
            description: |
              End of the daily window this rule applies within, in the site's local
              time. 24-hour `HH:MM`. A value earlier than `time_from` means the window
              runs past midnight into the following day. Null alongside a null
              `time_from` means the rule applies all day.
            example: '21:00'
          triggers:
            $ref: '#/components/schemas/YieldRuleTriggers'
          adjustment:
            $ref: '#/components/schemas/YieldRuleAdjustment'
          rounding:
            $ref: '#/components/schemas/yieldRounding'
          reporting_tier:
            $ref: '#/components/schemas/yieldReportingTier'
          created_at:
            type: string
            format: date-time
          updated_at:
            type: string
            format: date-time
            description: |
              When several rules could apply to the same slot, the most recently
              updated one wins.
        required:
          - id
          - offering_type
          - offering_id
          - site_id
          - created_batch_id
          - weekdays
          - time_from
          - time_to
          - triggers
          - adjustment
          - rounding
          - reporting_tier
          - created_at
          - updated_at
  - name: Zones
    description: |
      A `Zone` is a logical area within a site used to group resources
      for reservations and reporting (e.g. `Pool Deck`, `Hydrotherapy`,
      `Garden Cabanas`). Zones are referenced by area-booking types,
      practitioners, and other bookable resources.
paths:
  /admin/sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /admin/sites/{siteId}/invoices:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /admin/sites/{siteId}/invoices/{invoiceId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
      - $ref: '#/components/parameters/invoiceId'
  /admin/users/{userId}:
    parameters:
      - $ref: '#/components/parameters/userId'
  /admin/users/{userId}/sites:
    parameters:
      - $ref: '#/components/parameters/userId'
  /admin/users/{userId}/sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/userId'
      - $ref: '#/components/parameters/siteId'
  /admin/api-users/{userId}:
    parameters:
      - $ref: '#/components/parameters/parameters_userId'
  /admin/api-users/{userId}/sites:
    parameters:
      - $ref: '#/components/parameters/parameters_userId'
  /admin/api-users/{userId}/sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/parameters_userId'
      - $ref: '#/components/parameters/siteId'
  /api-users:
    get:
      summary: Get all API users
      description: |
        Use this endpoint to retrieve all API users
      tags:
        - Users
      operationId: listAllApiUsers
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/organisationId'
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/query'
        - $ref: '#/components/parameters/includeInactive'
      responses:
        '200':
          $ref: '#/components/responses/ListApiUsers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create an API user
      description: |
        Create a new API user (a non-human account intended to
        authenticate integrations) within the caller's organisation.
        The new user is attached to the supplied `site_id`, given the
        organisation's default API role, has their email pre-verified,
        and is issued a personal access token in the response — store
        it securely because Trybe will never return it again.

        Requires the caller's site-user to hold the `users:manage`
        permission on the target site. The `name` must be unique
        across API users in the organisation.
      tags:
        - Users
      operationId: createApiUser
      requestBody:
        $ref: '#/components/requestBodies/CreateApiUser'
      responses:
        '200':
          $ref: '#/components/responses/ShowApiUserWithToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /api-users/{userId}:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    get:
      summary: Get an API user
      description: |
        This endpoint retrieves an API user in Trybe
      operationId: getApiUser
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/ShowApiUser'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an API user
      description: |
        Rename an existing API user. The user's site memberships,
        roles and access token are left unchanged — only the
        human-readable label is updated. The new `name` must remain
        unique across API users in the organisation.

        Requires the caller's site-user to hold the `users:manage`
        permission on a site that the API user belongs to.
      operationId: updateApiUser
      tags:
        - Users
      requestBody:
        $ref: '#/components/requestBodies/UpdateApiUser'
      responses:
        '200':
          $ref: '#/components/responses/ShowApiUser'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an API user
      description: |
        Permanently delete an API user and invalidate any access
        tokens issued to them. Use this when an integration is
        retired or its credentials are believed to be compromised.

        Requires the caller's site-user to hold the `users:manage`
        permission on a site that the API user belongs to. The
        operation cannot be undone.
      operationId: deleteApiUser
      tags:
        - Users
      responses:
        '204':
          description: The API user was deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /meta/supported-locales:
    get:
      summary: Get supported locales
      description: |
        This endpoint lists the locales which are supported by the platform.

        A shopfront visitor may select a locale from this list to change the language of the shopfront,
        and one of these locales may be stored against a `Customer` or `Site`'s `preferred_locale`.
      operationId: listMetaSupportedLocales
      tags:
        - Meta
      responses:
        '200':
          $ref: '#/components/responses/ListSupportedLocales'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /meta/supported-currencies:
    get:
      summary: Get supported currencies
      description: |
        This endpoint lists the currencies which are supported by the platform.

        A `Site` may sell offerings to customers in one of the currencies listed here.
      operationId: listMetaSupportedCurrencies
      tags:
        - Meta
      responses:
        '200':
          $ref: '#/components/responses/ListSupportedCurrencies'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /meta/supported-timezones:
    get:
      summary: Get supported timezones
      description: |
        This endpoint lists the timezones which are supported by the platform.

        A `Site` may sell offerings to customers in one of the timezones listed here.
      operationId: listMetaSupportedTimezones
      tags:
        - Meta
      responses:
        '200':
          $ref: '#/components/responses/ListSupportedTimezones'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /meta/outbound-ips:
    get:
      summary: Get outbound IPs
      description: |
        This endpoint lists the outbound IP addresses used by the platform for the current environment.
      operationId: listOutboundIps
      tags:
        - Meta
      responses:
        '200':
          $ref: '#/components/responses/ListOutboundIps'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /sites:
    get:
      summary: Retrieve Sites
      description: Use this endpoint to retrieve a paginated list of `Site`s.
      operationId: listSites
      tags:
        - Sites
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/parameters_query'
        - $ref: '#/components/parameters/sortByQuery'
        - $ref: '#/components/parameters/sortByDirection'
      responses:
        '200':
          description: Sites were successfully retrieved.
          content:
            application/json:
              schema:
                type: object
                title: ListSites
                additionalProperties: false
                required:
                  - data
                  - links
                  - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Site'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Get the details of a single Site
      description: |
        Returns the full details of a single `Site` — including its name,
        locale, timezone, currency, and the organisation and brand it
        belongs to. Use this when you need the canonical record for a
        site identifier you already hold; for browsing the full list use
        `listSites`.

        Distinct from `getSite`, which is the admin-scoped read at
        `/shop/admin/sites/{siteId}`.
      tags:
        - Sites
      operationId: getSiteDetails
      responses:
        '200':
          $ref: '#/components/responses/ShowSite'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Site
      description: |
        Use this endpoint to update an existing `Site`.
      tags:
        - Sites
      operationId: updateSite
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSite'
      responses:
        '200':
          description: The Site was successfully updated
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                title: SiteResponse
                readOnly: true
                properties:
                  data:
                    $ref: '#/components/schemas/Site'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /sites/{siteId}/flags:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/logo:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Show a Site's logo
      tags:
        - Sites
      operationId: getSiteLogo
      description: |
        Use this endpoint to retrieve a `Site`'s logo.

        If the `Site` hasn't provided a logo, `data` will be `null`.
      responses:
        '200':
          $ref: '#/components/responses/ShowSiteLogo'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /sites/{siteId}/opera-fias-user:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/integration-user:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/calendar-events-v2:
    get:
      operationId: listCalendarEvents
      summary: List calendar events
      description: This endpoint lists calendar events.
      tags:
        - CalendarEvents
      parameters:
        - $ref: '#/components/parameters/date'
        - $ref: '#/components/parameters/events'
        - $ref: '#/components/parameters/includeCustomers'
        - $ref: '#/components/parameters/includePayments'
        - $ref: '#/components/parameters/includeSessionBookings'
        - $ref: '#/components/parameters/viewType'
        - $ref: '#/components/parameters/zoneId'
        - $ref: '#/components/parameters/parameters_siteId'
      responses:
        '200':
          description: Calendar events successfully retrieved.
          content:
            application/json:
              schema:
                title: ListCalendarEvents
                type: object
                additionalProperties: false
                required:
                  - data
                  - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CalendarEvent'
                  meta:
                    title: CalendarEventsMeta
                    type: object
                    additionalProperties: false
                    properties:
                      occupancy_per_hour:
                        type: array
                        items:
                          title: CalendarEventsOccupancyPerHour
                          type: object
                          additionalProperties: false
                          required:
                            - guests
                            - time
                          properties:
                            guests:
                              type: number
                            time:
                              type: string
                      occupancy_per_day:
                        type: number
                      occupancy_for_view:
                        type: number
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/calendar-notes:
    get:
      summary: List calendar notes
      description: |
        Returns a paginated list of `CalendarNote` objects for the given
        site. Notes can be filtered by an exact date or a date range to
        populate the calendar viewport.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listCalendarNotes
      tags:
        - CalendarNotes
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/parameters_date'
        - $ref: '#/components/parameters/dateFrom'
        - $ref: '#/components/parameters/dateTo'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCalendarNotes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a calendar note
      description: |
        Creates a new `CalendarNote` against a site for a given date.
        Requires the `RESERVATIONS_MANAGE` permission on the target site.
      operationId: createCalendarNote
      tags:
        - CalendarNotes
      requestBody:
        $ref: '#/components/requestBodies/CreateCalendarNote'
      responses:
        '201':
          $ref: '#/components/responses/ShowCalendarNote'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/calendar-notes/{calendarNoteId}:
    parameters:
      - $ref: '#/components/parameters/calendarNoteId'
    get:
      summary: Retrieve a calendar note
      description: |
        Returns a single `CalendarNote` by ID. Requires the
        `RESERVATIONS_VIEW` permission on the note's site.
      operationId: getCalendarNote
      tags:
        - CalendarNotes
      responses:
        '200':
          $ref: '#/components/responses/ShowCalendarNote'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a calendar note
      description: |
        Partially updates a `CalendarNote`. Every field is optional; only
        fields you send are written. Requires the `RESERVATIONS_MANAGE`
        permission on the note's current site (and the target site too,
        if `site_id` is changed).
      operationId: updateCalendarNote
      tags:
        - CalendarNotes
      requestBody:
        $ref: '#/components/requestBodies/UpdateCalendarNote'
      responses:
        '200':
          $ref: '#/components/responses/ShowCalendarNote'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a calendar note
      description: |
        Removes a `CalendarNote`. Requires the `RESERVATIONS_MANAGE`
        permission on the note's site.
      operationId: deleteCalendarNote
      tags:
        - CalendarNotes
      responses:
        '204':
          description: Calendar note deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/admin/sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-2'
  /shop/admin/sites/{siteId}/contract-to-stripe-customer:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-2'
  /shop/admin/sites/{siteId}/contract:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-2'
  /shop/admin/sites/{siteId}/stripe-customer:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-2'
  /shop/admin/sites/{siteId}/no-payment-gateway:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-2'
  /shop/basket/{basketId}/items:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Add an item to a Basket
      description: Use this endpoint to add an item to a `Basket`.
      operationId: createBasketItem
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/AddBasketItem'
      responses:
        '200':
          description: Successfully added an item to a `Basket`.
          content:
            application/json:
              schema:
                title: AddBasketItemResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/shop/offerings/{offeringType}/{offeringId}:
    parameters:
      - $ref: '#/components/parameters/offeringId'
      - $ref: '#/components/parameters/offeringType'
    get:
      summary: Retrieve an Offering
      description: Use this endpoint to retrieve an `Offering`.
      operationId: getShopOffering
      tags:
        - Shop
      responses:
        '200':
          description: Successfully retrieved an `Offering`.
          content:
            application/json:
              schema:
                title: ShowShopOfferingResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    description: |
                      The offering record matching the requested `offeringType`
                      and `offeringId`. The concrete shape depends on the
                      offering type (e.g. `appointment`, `area_booking`,
                      `package`, `product`, `session`).
                    oneOf:
                      - $ref: '#/components/schemas/Appointment'
                      - $ref: '#/components/schemas/AreaBooking'
                      - $ref: '#/components/schemas/Package'
                      - $ref: '#/components/schemas/Product'
                      - $ref: '#/components/schemas/Session'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/terminal-requests/identity:
    post:
      summary: Create a request to identify a Wearable Device
      tags:
        - TerminalRequests
      operationId: createIdentityRequest
      description: |
        This endpoint sends a request to the terminal to identify a wearable device.
      requestBody:
        $ref: '#/components/requestBodies/CreateIdentityRequest'
      responses:
        '200':
          $ref: '#/components/responses/ShowTerminalRequest'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/terminal-requests/associate-wearable:
    post:
      summary: Create a request to associate a Wearable Device
      tags:
        - TerminalRequests
      operationId: createWearableAssociationRequest
      description: |
        This endpoint sends a request to the terminal to associate a wearable device.
      requestBody:
        $ref: '#/components/requestBodies/CreateWearableAssociationRequest'
      responses:
        '200':
          $ref: '#/components/responses/ShowTerminalRequest'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/terminal-requests/{terminalRequestId}:
    parameters:
      - $ref: '#/components/parameters/terminalRequestId'
    get:
      summary: Show a Terminal Request
      description: |
        This endpoint retrieves a Terminal Request by ID.
      tags:
        - TerminalRequests
      operationId: getTerminalRequest
      responses:
        '200':
          $ref: '#/components/responses/ShowTerminalRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/terminal-requests/{terminalRequestId}/cancel:
    parameters:
      - $ref: '#/components/parameters/terminalRequestId'
    post:
      summary: Cancel a Terminal Request
      tags:
        - TerminalRequests
      operationId: actionCancelTerminalRequest
      description: |
        This endpoint cancels a Terminal Request.
      responses:
        '200':
          $ref: '#/components/responses/ShowTerminalRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/terminal-tokenisations:
    post:
      summary: Create a request to tokenise a customer's card details
      tags:
        - TerminalTokenisations
      operationId: createCardTokenisationRequest
      description: |
        This endpoint sends a request to the terminal to tokenise a customer's card details.
      requestBody:
        $ref: '#/components/requestBodies/CreateCardTokenisationRequest'
      responses:
        '200':
          $ref: '#/components/responses/ShowCardTokenisationRequest'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/terminal-tokenisations/{paymentId}:
    parameters:
      - $ref: '#/components/parameters/paymentId'
    get:
      summary: Show a Card Tokenisation Request
      description: |
        This endpoint retrieves a Card Tokenisation Request by Payment ID.
      tags:
        - TerminalTokenisations
      operationId: getCardTokenisationRequest
      responses:
        '200':
          $ref: '#/components/responses/ShowCardTokenisationRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/terminal-tokenisations/{paymentId}/cancel:
    parameters:
      - $ref: '#/components/parameters/paymentId'
    post:
      summary: Cancel a Card Tokenisation Request
      tags:
        - TerminalTokenisations
      operationId: actionCancelCardTokenisationRequest
      description: |
        This endpoint cancels a Card Tokenisation Request.
      responses:
        '200':
          $ref: '#/components/responses/ShowCardTokenisationRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointments-v2:
    get:
      summary: List Appointments
      description: Use this endpoint to list `Appointment`s.
      operationId: listAppointments
      tags:
        - Appointments
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/orderSubmittedAtFrom'
        - $ref: '#/components/parameters/orderSubmittedAtTo'
        - $ref: '#/components/parameters/practitionerId'
        - $ref: '#/components/parameters/roomId'
        - $ref: '#/components/parameters/parameters_zoneId'
      responses:
        '200':
          description: Successfully retrieved `Appointment`s.
          content:
            application/json:
              schema:
                title: ListAppointmentsResponse
                allOf:
                  - $ref: '#/components/schemas/Pagination'
                  - title: ListAppointmentsResponseData
                    type: object
                    additionalProperties: false
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/schemas_Appointment'
                      totals:
                        $ref: '#/components/schemas/Totals'
                    required:
                      - data
                      - totals
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/appointments:
    get:
      summary: List Appointments
      description: |
        Returns a paginated list of `Appointment`s, optionally filtered by
        the date range the appointments fall in, the date range that the
        underlying `Order`s were submitted in, and by `Practitioner`,
        `Room`, or `Zone`. Appointments are ordered by `start_time`
        ascending.

        This endpoint powers the calendar list views, day-sheet exports
        (via the CSV variant returned when `Accept: text/csv`), and any
        third-party reporting integration that needs the same data the
        Trybe dashboard renders.
      operationId: listShopAppointments
      tags:
        - Appointments
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/orderSubmittedAtFrom'
        - $ref: '#/components/parameters/orderSubmittedAtTo'
        - $ref: '#/components/parameters/practitionerId'
        - $ref: '#/components/parameters/roomId'
        - $ref: '#/components/parameters/parameters_zoneId'
      responses:
        '200':
          description: Successfully retrieved `Appointment`s.
          content:
            application/json:
              schema:
                title: ListShopAppointmentsResponse
                allOf:
                  - $ref: '#/components/schemas/Pagination'
                  - title: ListShopAppointmentsResponseData
                    type: object
                    additionalProperties: false
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/schemas_Appointment'
                      totals:
                        $ref: '#/components/schemas/Totals'
                    required:
                      - data
                      - totals
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/appointments/{appointmentId}:
    parameters:
      - $ref: '#/components/parameters/appointmentId'
    get:
      summary: Retrieve an Appointment
      description: |
        Retrieves a single `Appointment` by ID. Use this endpoint when you
        have an appointment ID returned by `listShopAppointments`,
        `createBasketAppointmentItem`, or a webhook payload, and need the
        canonical record — including its current `status`, `stage`,
        assigned `Practitioner`s, `Room`, guest associations, and order
        context.
      operationId: getAppointment
      tags:
        - Appointments
      responses:
        '200':
          description: The `Appointment` was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetAppointmentResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Appointment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Appointment
      description: |
        Updates an `Appointment` in place. Common uses are reassigning the
        practitioner, moving the appointment to a different `Room`,
        rescheduling the `start_time`, or progressing the underlying
        `Order` through stages (e.g. marking the customer as `arrived`,
        `in_treatment`, or `checked_out`).

        The update is routed through the basket / availability layer, so
        the request is validated against the same rules a fresh booking
        would face — overlapping practitioner bookings, room capacity,
        site opening hours, and equipment availability are all enforced.
        Users with the `reservations.override-rules` permission can bypass
        these checks server-side; everyone else will receive a `400 Bad
        Request` with the specific availability conflict.

        The `move` object is a convenience for calendar drag-and-drop:
        pass `move.resource_type` of `practitioner` or `room` plus the
        `from_id` and `to_id` to swap the assigned resource without
        spelling out the full `practitioner_ids` list. When only `stage`
        is supplied the appointment slot is left untouched and the change
        is applied to the parent order, saving the availability round-trip
        entirely.
      operationId: updateAppointment
      tags:
        - Appointments
      requestBody:
        description: The fields to update on the appointment.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAppointment'
      responses:
        '200':
          description: The `Appointment` was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateAppointmentResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Appointment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-bookings/{areaBookingId}:
    parameters:
      - $ref: '#/components/parameters/areaBookingId'
    get:
      summary: Retrieve an AreaBooking
      description: |
        Retrieves a single `AreaBooking` by ID. Use this when you have an
        `AreaBooking` ID from `createBasketAreaBookingItem`, a webhook
        payload, or a calendar view and need the canonical reservation
        record — including which `BookableArea`s are assigned, the
        customer details, and the parent order context.
      operationId: getAreaBooking
      tags:
        - AreaBookings
      responses:
        '200':
          description: The `AreaBooking` was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetAreaBookingResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_AreaBooking'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an AreaBooking
      description: |
        Updates an existing `AreaBooking` — typically to reassign the
        booked areas, reschedule the time slot, adjust the duration, or
        progress the parent order through its check-in stages.

        The update is routed through the basket / availability layer, so
        every change is validated against the same rules as a fresh
        booking: overlapping area reservations, capacity, site opening
        hours, and the parent `AreaBookingType`'s permitted areas are all
        enforced. Users with the `reservations.override-rules` permission
        can bypass these checks server-side; everyone else will receive a
        `400 Bad Request` describing the conflict.

        When only `stage` is supplied the booking slot is left untouched
        and the change is applied to the parent order, saving the
        availability round-trip entirely.
      operationId: updateAreaBooking
      tags:
        - AreaBookings
      requestBody:
        description: The fields to update on the area booking.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAreaBooking'
      responses:
        '200':
          description: The `AreaBooking` was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateAreaBookingResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_AreaBooking'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-codes:
    get:
      summary: List VoucherCodes
      description: |
        Returns a paginated list of `VoucherCode`s. Use the query
        parameters to narrow the result set by code substring, status,
        amount, balance, creation date, site, voucher type, expiry window,
        or fulfilment status. The result is ordered by `created_at`
        descending so the newest voucher codes appear first.

        This endpoint powers the voucher management screens in the Trybe
        dashboard and any third-party integration that needs the same
        view — for example a fulfilment provider polling for vouchers
        with `fulfillment_status=needs_dispatching`.
      operationId: listVoucherCodes
      tags:
        - VoucherCodes
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/siteIdFilter'
        - $ref: '#/components/parameters/code'
        - $ref: '#/components/parameters/status'
        - $ref: '#/components/parameters/amount'
        - $ref: '#/components/parameters/balance'
        - $ref: '#/components/parameters/createdSince'
        - $ref: '#/components/parameters/voucherTypeId'
        - $ref: '#/components/parameters/expiredRangeFrom'
        - $ref: '#/components/parameters/expiredRangeTo'
        - $ref: '#/components/parameters/fulfillmentStatus'
      responses:
        '200':
          description: Successfully retrieved `VoucherCode`s.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListVoucherCodesResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/voucher-codes/bulk:
    post:
      summary: Bulk-create VoucherCodes
      description: |
        Imports an array of pre-existing voucher codes in a single request,
        creating each as a `VoucherCode` on the given site. This endpoint is
        intended for migrating voucher codes from a third-party system into
        Trybe — each code must be alphanumeric and unique within the
        organisation.

        Every code in the batch is validated before any are written. If
        validation fails the entire request is rejected with a `422` and
        a per-field error map so you can correct and re-submit without
        wondering which records were written.

        On success, all created `VoucherCode` objects are returned in the
        same order as the request array. The endpoint also creates an
        internal `Import` record that can be cross-referenced with the
        Trybe dashboard's import history.

        Required permission: `settings:manage`.
      operationId: actionBulkCreateVoucherCodes
      tags:
        - VoucherCodes
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      requestBody:
        required: true
        description: The voucher codes to import.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateVoucherCodesRequest'
      responses:
        '200':
          description: All voucher codes were successfully created.
          content:
            application/json:
              schema:
                title: BulkCreateVoucherCodesResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VoucherCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-codes/{voucherCodeId}:
    parameters:
      - $ref: '#/components/parameters/voucherCodeId'
    get:
      summary: Retrieve a VoucherCode
      description: |
        Retrieves a single `VoucherCode` by ID, including every
        `redemption` recorded against it. Use this when you have a voucher
        ID from a webhook payload, the `listVoucherCodes` response, or a
        customer-service search, and need the canonical record plus full
        redemption history.

        Trashed (soft-deleted) voucher codes are returned by this
        endpoint with `status` of `revoked`, so customer-service flows can
        inspect revoked codes without a separate lookup.
      operationId: getVoucherCode
      tags:
        - VoucherCodes
      responses:
        '200':
          description: The `VoucherCode` was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetVoucherCodeResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VoucherCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a VoucherCode
      description: |
        Updates a `VoucherCode` in place. The two fields most commonly
        changed are `valid_to_date` (to extend or shorten the voucher's
        expiry window) and `fulfillment_status` (to record physical
        dispatch).

        The voucher's `status` is recalculated automatically when
        `valid_to_date` is changed: pushing the date past today on an
        `expired` voucher will move it back to `unredeemed` (or
        `partially_redeemed` if there have been redemptions); setting the
        date before today on a non-revoked voucher will move it to
        `expired`. `revoked` vouchers are never reactivated by a
        `valid_to_date` change.
      operationId: updateVoucherCode
      tags:
        - VoucherCodes
      requestBody:
        description: The fields to update on the voucher code.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateVoucherCode'
      responses:
        '200':
          description: The `VoucherCode` was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateVoucherCodeResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VoucherCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/appointment-types:
    parameters:
      - $ref: '#/components/parameters/requiredSiteId'
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
      - $ref: '#/components/parameters/archivedQuery'
      - $ref: '#/components/parameters/parameters_practitionerId'
      - $ref: '#/components/parameters/categoryId'
    get:
      summary: List appointment types
      description: |
        Returns a paginated list of `AppointmentType`s configured at the given site,
        ordered by name. Use this to power a settings dashboard or to populate a
        booking-frame selector. The list includes archived items only when
        `archived=true` is passed.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listAppointmentTypes
      tags:
        - AppointmentTypes
      responses:
        '200':
          $ref: '#/components/responses/ListAppointmentTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create an appointment type
      description: |
        Creates a new `AppointmentType` at the given site(s). The minimum body is
        `name` + `site_ids`; everything else has sensible defaults.
        Requires the `SETTINGS_MANAGE` permission on every site listed in `site_ids`.

        If `max_guests > 1`, `shop_practitioner_selection` is forced to `null`
        server-side regardless of the value sent — multi-guest appointments don't
        support per-guest practitioner choice today.
      operationId: createAppointmentType
      tags:
        - AppointmentTypes
      requestBody:
        $ref: '#/components/requestBodies/CreateAppointmentType'
      responses:
        '201':
          $ref: '#/components/responses/ShowAppointmentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/appointment-types/{appointmentTypeId}:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
    get:
      summary: Retrieve an appointment type
      description: |
        Returns the full `AppointmentType` for the given ID. Use this to
        populate an admin edit screen or to look up settings when building a
        booking against a known offering.
      operationId: getAppointmentType
      tags:
        - AppointmentTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an appointment type
      description: |
        Partially updates an `AppointmentType`. Every field is optional; only
        fields you send are written. Fields you omit retain their current
        values.

        Requires the `SETTINGS_MANAGE` permission on at least one of the
        appointment type's sites. As with create, `max_guests > 1` forces
        `shop_practitioner_selection` to null.
      operationId: updateAppointmentType
      tags:
        - AppointmentTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateAppointmentType'
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an appointment type
      description: |
        Soft-deletes the appointment type. Existing bookings are unaffected;
        the type is removed from new-booking flows. Use `POST .../restore` to
        bring it back.

        **409 Conflict** if the appointment type is referenced by any
        `Package`'s item choices — remove it from those packages first.
      operationId: deleteAppointmentType
      tags:
        - AppointmentTypes
      responses:
        '204':
          description: Appointment type deleted successfully.
        '400':
          description: |
            Deletion blocked because the appointment type is referenced by
            existing packages. The response body lists the package names.
          content:
            application/json:
              schema:
                title: AppointmentTypeInUseByPackages
                type: object
                additionalProperties: false
                required:
                  - message
                properties:
                  message:
                    type: string
                    description: |
                      Human-readable message naming the packages that still
                      reference this appointment type.
                    example: This appointment type exists in 2 packages. Remove it from the following packages before continuing&#58; Spa Day, Couples Retreat
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointment-types/{appointmentTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
    post:
      summary: Duplicate an appointment type
      description: |
        Creates a copy of an existing `AppointmentType` with new fields applied
        from the request body. Useful when seeding a new offering off an
        existing one rather than building from scratch. The new appointment
        type is created under the same site(s) and organisation as the
        original; you can override most fields by sending them in the body.

        Requires the `SETTINGS_MANAGE` permission on the original appointment
        type's site.
      operationId: copyAppointmentType
      tags:
        - AppointmentTypes
      requestBody:
        $ref: '#/components/requestBodies/CopyAppointmentType'
      responses:
        '201':
          $ref: '#/components/responses/ShowAppointmentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/appointment-types/{appointmentTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
    post:
      summary: Restore a deleted appointment type
      description: |
        Un-deletes a previously soft-deleted `AppointmentType`. The appointment
        type returns to its pre-deletion state, including all sites,
        practitioners, and rules. Existing bookings against it remain
        unaffected by either the delete or the restore.

        Requires the `SETTINGS_MANAGE` permission on the appointment type's
        site. No request body.
      operationId: restoreAppointmentType
      tags:
        - AppointmentTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointment-types/{appointmentTypeId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
    get:
      summary: List availability rules for an appointment type
      tags:
        - AppointmentTypes
      operationId: listAppointmentTypeAvailabilityRules
      description: |
        Returns all `AvailabilityRule`s configured on an `AppointmentType`.
        Availability rules carve up the working calendar into windows when
        bookings can or cannot happen — useful for blocking holidays,
        restricting weekend hours, or making a treatment available only
        during specific seasons.

        Rule semantics: any `is_available: false` rule overrides any
        `is_available: true` rule for the same time period.
      responses:
        '200':
          $ref: '#/components/responses/ListAppointmentTypeAvailabilityRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an availability rule for an appointment type
      tags:
        - AppointmentTypes
      operationId: createAppointmentTypeAvailabilityRule
      description: |
        Adds a new `AvailabilityRule` to an `AppointmentType`. With
        `is_available: true` the rule opens new bookable windows; with
        `is_available: false` it blocks them. Omitting date/time/weekday
        filters means the rule applies always.

        Requires the `SETTINGS_MANAGE` permission on the appointment type's
        site.
      requestBody:
        $ref: '#/components/requestBodies/CreateAppointmentTypeAvailabilityRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowAppointmentTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/appointment-types/{appointmentTypeId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
      - $ref: '#/components/parameters/availabilityRuleId'
    get:
      summary: Retrieve an availability rule
      tags:
        - AppointmentTypes
      operationId: getAppointmentTypeAvailabilityRule
      description: Returns a single `AvailabilityRule` belonging to the given `AppointmentType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an availability rule
      tags:
        - AppointmentTypes
      operationId: updateAppointmentTypeAvailabilityRule
      description: |
        Replaces an `AvailabilityRule`. The server validates the same shape
        as on create, so `is_available` is required. Requires the
        `SETTINGS_MANAGE` permission on the appointment type's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateAppointmentTypeAvailabilityRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an availability rule
      tags:
        - AppointmentTypes
      operationId: deleteAppointmentTypeAvailabilityRule
      description: |
        Removes an `AvailabilityRule` from an `AppointmentType`. Calendar
        availability is recomputed from the remaining rules. Existing
        bookings are unaffected.
      responses:
        '204':
          description: Availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointment-types/{appointmentTypeId}/price-rules:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
    get:
      summary: List price rules for an appointment type
      tags:
        - AppointmentTypes
      operationId: listAppointmentTypePriceRules
      description: |
        Returns all `PriceRule`s configured for the given `AppointmentType`,
        filterable by date range and weekday. Price rules determine the price
        a customer pays based on when the appointment is booked — peak vs
        off-peak, weekday vs weekend, seasonal overrides, etc. The first
        rule whose conditions match the booking time wins.
      parameters:
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/weekdays'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListAppointmentTypePriceRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a price rule for an appointment type
      tags:
        - AppointmentTypes
      operationId: createAppointmentTypePriceRule
      description: |
        Adds a new `PriceRule` to an `AppointmentType`. Rules with date and
        time ranges + weekday filters combine to express most pricing
        scenarios — peak vs off-peak, weekday vs weekend, seasonal
        overrides. The first rule whose conditions match a given booking
        wins. Omitting all filters creates a fallback "always applies" rule.

        When `offering_standard_price` is enabled for the site, the appointment
        type's `standard_price` must be set before a price rule can be created. A
        zero amount counts as set. Requires the `SETTINGS_MANAGE` permission on
        the appointment type's site.
      requestBody:
        $ref: '#/components/requestBodies/CreateAppointmentTypePriceRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowAppointmentTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/appointment-types/{appointmentTypeId}/price-rules/{priceRuleId}:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
      - $ref: '#/components/parameters/priceRuleId'
    get:
      summary: Retrieve a price rule
      tags:
        - AppointmentTypes
      operationId: getAppointmentTypePriceRule
      description: Returns a single `PriceRule` belonging to the given `AppointmentType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a price rule
      tags:
        - AppointmentTypes
      operationId: updateAppointmentTypePriceRule
      description: |
        Partially updates a `PriceRule`. Every field is optional; only fields
        you send are written. When `offering_standard_price` is enabled for the
        site, the appointment type's `standard_price` must be set before a price
        rule can be updated. A zero amount counts as set. Requires the
        `SETTINGS_MANAGE` permission on the appointment type's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateAppointmentTypePriceRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a price rule
      tags:
        - AppointmentTypes
      operationId: deleteAppointmentTypePriceRule
      description: |
        Removes a `PriceRule` from an `AppointmentType`. Existing bookings
        already priced under this rule are unaffected — they retain the
        price set at booking time. When `offering_standard_price` is enabled for
        the site, the appointment type's `standard_price` must be set before a
        price rule can be deleted. A zero amount counts as set.
      responses:
        '204':
          description: Price rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/appointment-types/{appointmentTypeId}/suggest-description:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
  /shop/appointment-types/{appointmentTypeId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for an AppointmentType
      description: Returns the localised `name`, `description`, `meta_title` and `meta_description` for the given locale.
      operationId: getAppointmentTypeLocaleStrings
      tags:
        - AppointmentTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for an AppointmentType
      description: Sets the localised `name`, `description`, `meta_title` and/or `meta_description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateAppointmentTypeLocaleStrings
      tags:
        - AppointmentTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateAppointmentTypeLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateAppointmentTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-booking-types:
    parameters:
      - $ref: '#/components/parameters/requiredSiteId'
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
      - $ref: '#/components/parameters/archivedQuery'
      - $ref: '#/components/parameters/parameters_categoryId'
    get:
      summary: List area booking types
      description: |
        Returns a paginated list of `AreaBookingType`s configured at the given
        site, ordered by name. Use this to power a settings dashboard or to
        populate a booking-frame selector for cabanas, pool loungers, treatment
        pods and other bookable spaces. The list includes archived items only
        when `archived=true` is passed.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listAreaBookingTypes
      tags:
        - AreaBookingTypes
      responses:
        '200':
          $ref: '#/components/responses/ListAreaBookingTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create an area booking type
      description: |
        Creates a new `AreaBookingType` at the given site. The required body
        is `name`, `start_time_interval`, `duration_interval`, `min_duration`
        and `max_duration`; everything else has sensible defaults.

        Requires the `SETTINGS_MANAGE` permission on the site referenced via
        the `Trybe-Site-Id` header. The newly created type is attributed to
        the caller's primary organisation.
      operationId: createAreaBookingType
      tags:
        - AreaBookingTypes
      requestBody:
        $ref: '#/components/requestBodies/CreateAreaBookingType'
      responses:
        '201':
          $ref: '#/components/responses/ShowAreaBookingType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-booking-types/{areaBookingTypeId}:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
    get:
      summary: Retrieve an area booking type
      description: |
        Returns the full `AreaBookingType` for the given ID. Use this to
        populate an admin edit screen or to look up settings when building a
        booking against a known offering.
      operationId: getAreaBookingType
      tags:
        - AreaBookingTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an area booking type
      description: |
        Partially updates an `AreaBookingType`. Every field is optional; only
        fields you send are written. Fields you omit retain their current
        values.

        Requires the `SETTINGS_MANAGE` permission on the area booking type's
        site.
      operationId: updateAreaBookingType
      tags:
        - AreaBookingTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateAreaBookingType'
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an area booking type
      description: |
        Soft-deletes the area booking type. Existing bookings are unaffected;
        the type is removed from new-booking flows. Use `POST .../restore` to
        bring it back.

        **400 Bad Request** if the area booking type is referenced by any
        `Package`'s item choices — remove it from those packages first.
      operationId: deleteAreaBookingType
      tags:
        - AreaBookingTypes
      responses:
        '204':
          description: Area booking type deleted successfully.
        '400':
          description: |
            Deletion blocked because the area booking type is referenced by
            existing packages. The response body lists the package names.
          content:
            application/json:
              schema:
                title: AreaBookingTypeInUseByPackages
                type: object
                additionalProperties: false
                required:
                  - message
                properties:
                  message:
                    type: string
                    description: |
                      Human-readable message naming the packages that still
                      reference this area booking type.
                    example: This booking type exists in 2 packages. Remove it from the following packages before continuing&#58; Cabana Day Pass, Wellness Retreat
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/area-booking-types/{areaBookingTypeId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
    get:
      summary: List availability rules for an area booking type
      tags:
        - AreaBookingTypes
      operationId: listAreaBookingTypeAvailabilityRules
      description: |
        Returns all `AvailabilityRule`s configured on an `AreaBookingType`.
        Availability rules carve up the working calendar into windows when
        bookings can or cannot happen — useful for blocking maintenance days,
        restricting cabana hours, or opening the pool deck only during
        summer months.

        Rule semantics: any `is_available: false` rule overrides any
        `is_available: true` rule for the same time period.
      responses:
        '200':
          $ref: '#/components/responses/ListAreaBookingTypeAvailabilityRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an availability rule for an area booking type
      tags:
        - AreaBookingTypes
      operationId: createAreaBookingTypeAvailabilityRule
      description: |
        Adds a new `AvailabilityRule` to an `AreaBookingType`. With
        `is_available: true` the rule opens new bookable windows; with
        `is_available: false` it blocks them. Omitting date/time/weekday
        filters means the rule applies always.

        Requires the `SETTINGS_MANAGE` permission on the area booking type's
        site.
      requestBody:
        $ref: '#/components/requestBodies/CreateAreaBookingTypeAvailabilityRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowAreaBookingTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-booking-types/{areaBookingTypeId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
      - $ref: '#/components/parameters/availabilityRuleId'
    get:
      summary: Retrieve an availability rule
      tags:
        - AreaBookingTypes
      operationId: getAreaBookingTypeAvailabilityRule
      description: Returns a single `AvailabilityRule` belonging to the given `AreaBookingType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an availability rule
      tags:
        - AreaBookingTypes
      operationId: updateAreaBookingTypeAvailabilityRule
      description: |
        Replaces an `AvailabilityRule`. The server validates the same shape
        as on create, so `is_available` is required. Requires the
        `SETTINGS_MANAGE` permission on the area booking type's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateAreaBookingTypeAvailabilityRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an availability rule
      tags:
        - AreaBookingTypes
      operationId: deleteAreaBookingTypeAvailabilityRule
      description: |
        Removes an `AvailabilityRule` from an `AreaBookingType`. Calendar
        availability is recomputed from the remaining rules. Existing
        bookings are unaffected.
      responses:
        '204':
          description: Availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/area-booking-types/{areaBookingTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
    post:
      summary: Duplicate an area booking type
      description: |
        Creates a copy of an existing `AreaBookingType` with new fields applied
        from the request body. Useful when seeding a new offering off an
        existing one rather than building from scratch. The new area booking
        type is created under the same site as the original; you can override
        most fields by sending them in the body.

        Requires the `SETTINGS_MANAGE` permission on the original area booking
        type's site.
      operationId: copyAreaBookingType
      tags:
        - AreaBookingTypes
      requestBody:
        $ref: '#/components/requestBodies/CopyAreaBookingType'
      responses:
        '201':
          $ref: '#/components/responses/ShowAreaBookingType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-booking-types/{areaBookingTypeId}/price-rules:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
    get:
      summary: List price rules for an area booking type
      tags:
        - AreaBookingTypes
      operationId: listAreaBookingTypePriceRules
      description: |
        Returns all price rules configured for the given `AreaBookingType`,
        filterable by date range and weekday. Price rules determine the price
        a customer pays based on when the booking is placed and how long it
        lasts — peak vs off-peak, weekday vs weekend, day-rate vs half-day.
        The first rule whose conditions match the booking wins.
      parameters:
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/weekdays'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListAreaBookingTypePriceRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a price rule for an area booking type
      tags:
        - AreaBookingTypes
      operationId: createAreaBookingTypePriceRule
      description: |
        Adds a new price rule to an `AreaBookingType`. Rules with date and
        time ranges + weekday filters combine to express most pricing
        scenarios — peak vs off-peak, weekday vs weekend, seasonal
        overrides. The `max_duration` is required and the price applies to
        bookings up to that length. The first rule whose conditions match a
        given booking wins.

        When `offering_standard_price` is enabled for the site, the area booking
        type's `standard_price` must be set before a price rule can be created. A
        zero amount counts as set. Requires the `SETTINGS_MANAGE` permission on
        the area booking type's site.
      requestBody:
        $ref: '#/components/requestBodies/CreateAreaBookingTypePriceRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowAreaBookingTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-booking-types/{areaBookingTypeId}/price-rules/{priceRuleId}:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
      - $ref: '#/components/parameters/priceRuleId'
    get:
      summary: Retrieve a price rule
      tags:
        - AreaBookingTypes
      operationId: getAreaBookingTypePriceRule
      description: Returns a single price rule belonging to the given `AreaBookingType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a price rule
      tags:
        - AreaBookingTypes
      operationId: updateAreaBookingTypePriceRule
      description: |
        Partially updates a price rule. Every field is optional; only fields
        you send are written. When `offering_standard_price` is enabled for the
        site, the area booking type's `standard_price` must be set before a price
        rule can be updated. A zero amount counts as set. Requires the
        `SETTINGS_MANAGE` permission on the area booking type's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateAreaBookingTypePriceRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a price rule
      tags:
        - AreaBookingTypes
      operationId: deleteAreaBookingTypePriceRule
      description: |
        Removes a price rule from an `AreaBookingType`. Existing bookings
        already priced under this rule are unaffected — they retain the
        price set at booking time. When `offering_standard_price` is enabled for
        the site, the area booking type's `standard_price` must be set before a
        price rule can be deleted. A zero amount counts as set.
      responses:
        '204':
          description: Price rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/area-booking-types/{areaBookingTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
    post:
      summary: Restore a deleted area booking type
      description: |
        Un-deletes a previously soft-deleted `AreaBookingType`. The area
        booking type returns to its pre-deletion state, including all areas
        and rules. Existing bookings against it remain unaffected by either
        the delete or the restore.

        Requires the `SETTINGS_MANAGE` permission on the area booking type's
        site. No request body.
      operationId: restoreAreaBookingType
      tags:
        - AreaBookingTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/area-booking-types/{areaBookingTypeId}/suggest-description:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
  /shop/area-booking-types/{areaBookingTypeId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for an AreaBookingType
      description: Returns the localised `name`, `description`, `meta_title` and `meta_description` for the given locale.
      operationId: getAreaBookingTypeLocaleStrings
      tags:
        - AreaBookingTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowAreaBookingTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for an AreaBookingType
      description: Sets the localised `name`, `description`, `meta_title` and/or `meta_description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateAreaBookingTypeLocaleStrings
      tags:
        - AreaBookingTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateAreaBookingTypeLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateAreaBookingTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket:
    post:
      summary: Create a Basket
      description: |
        Creates a new `Basket` at a `Site`. The basket is the central
        object in Trybe's checkout flow — it accumulates items
        (appointments, area bookings, products, vouchers, memberships,
        etc.), customer details, coupons, vouchers, and payments before
        being submitted to create an `Order`.

        If the request is authenticated as a `Customer` (e.g. via a
        customer access token), that customer is linked to the basket
        automatically. Otherwise pass `customer_id` to associate an
        existing customer, or omit it and call `POST
        /shop/basket/{basketId}/customer` later in the flow.

        A "Website" `SalesChannel` is provisioned for the site's
        organisation on first use and reused thereafter.
      operationId: createBasket
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/CreateBasket'
      responses:
        '200':
          description: The newly created `Basket`.
          content:
            application/json:
              schema:
                title: CreateBasketResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}:
    parameters:
      - $ref: '#/components/parameters/basketId'
    get:
      summary: Retrieve a Basket
      description: |
        Returns the full state of a `Basket` — its items, guests,
        payments, applied coupons and vouchers, totals, and submit
        state. This is the canonical endpoint frontends call after any
        mutating action to reconcile their local view of the cart.

        Baskets that were submitted more than an hour ago and aren't
        attached to a visit return `404` so that completed checkouts
        can't be re-rendered by stale links.
      operationId: getBasket
      tags:
        - Baskets
      responses:
        '200':
          description: The requested `Basket`.
          content:
            application/json:
              schema:
                title: GetBasketResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Basket
      description: |
        Updates a small set of basket-level metadata. Use this to record
        special requests captured during checkout (e.g. dietary
        requirements, accessibility notes).

        Returns `400 Bad Request` if the basket has already been
        submitted or otherwise locked.
      operationId: updateBasket
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/UpdateBasket'
      responses:
        '200':
          description: The updated `Basket`.
          content:
            application/json:
              schema:
                title: UpdateBasketResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/checkout-config:
    parameters:
      - $ref: '#/components/parameters/basketId'
    get:
      summary: Get Basket checkout configuration
      description: |
        Returns the legal and clinical pre-flight data a shop frontend
        needs to render the final checkout step:

        - `terms` — the booking terms & conditions the customer must
          accept, assembled from site, offering, and basket-level
          sources.
        - `contraindications` — clinical contraindications attached to
          any appointment offerings in the basket (filtered to entries
          the customer must positively confirm).
        - `voucher_payment_enabled` — whether external voucher
          redemption is configured for the basket's site.
      operationId: getBasketCheckoutConfig
      tags:
        - Baskets
      responses:
        '200':
          description: The checkout configuration for the basket.
          content:
            application/json:
              schema:
                title: GetBasketCheckoutConfigResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/BasketCheckoutConfig'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/coupons:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Apply a coupon to a Basket
      description: |
        Validates and applies a `CouponCode` to the basket. Coupons can
        grant percentage or fixed-amount discounts, automatic free
        items, or unlock pricing tiers — the basket totals are
        recalculated on success.

        Customer-facing flows can only add coupons while the basket is
        `in_progress`. Staff (authenticated as a `User`) bypass that
        restriction provided they have the `reservations.manage`
        permission for the site.

        Returns `400 Bad Request` with a human-readable reason when the
        coupon is invalid, expired, fully redeemed, or incompatible
        with the basket's items.
      operationId: createBasketCoupon
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/CreateBasketCoupon'
      responses:
        '200':
          description: The updated `Basket` with the coupon applied.
          content:
            application/json:
              schema:
                title: CreateBasketCouponResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/coupons/{coupon}:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/couponCodeId'
    delete:
      summary: Remove a coupon from a Basket
      description: |
        Detaches a previously-applied `CouponCode` from the basket. Any
        discount the coupon was contributing is reversed and the totals
        are recalculated.

        As with `POST /shop/basket/{basketId}/coupons`, customer-facing
        flows can only remove coupons while the basket is `in_progress`;
        staff (authenticated as a `User`) need the `reservations.manage`
        permission for the site.
      operationId: deleteBasketCoupon
      tags:
        - Baskets
      responses:
        '204':
          description: The coupon was successfully removed from the basket.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/customer:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Set the customer on a Basket
      description: |
        Attaches a `Customer` to the basket so the resulting `Order` is
        correctly attributed and surfaced in the customer's history.
        There are three modes:

        1. **Authenticated customer** — the request is authenticated as a
           `Customer` for the basket's brand. The authenticated customer
           is linked directly. If they don't have a phone number on file,
           supply one with `phone` (and optionally `phone_country`).
        2. **Existing customer by email** — pass `email`, `first_name`,
           `last_name`, and optionally `phone`. If a customer with that
           email already exists for the brand they are linked; otherwise
           a new `Customer` is created using these details.
        3. **Guest checkout** — the same payload as mode 2 is used; the
           newly-created customer is linked to the basket and saved
           against any marketing preferences supplied.

        Phone numbers are normalised to E.164 using `phone_country` (or
        the site's country code) as the default region.
      operationId: actionSetBasketCustomer
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/SetBasketCustomer'
      responses:
        '200':
          description: The updated `Basket` with the customer attached.
          content:
            application/json:
              schema:
                title: SetBasketCustomerResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/customer-credits:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Apply a customer credit to a Basket
      description: |
        Applies one of the customer's outstanding `CustomerCredit`
        balances against the basket. Customer credits are issued by
        operators as compensation, refunds-to-store-credit, or loyalty
        rewards; once applied to a basket they reduce the outstanding
        payment amount immediately.

        Returns `400 Bad Request` if the credit can't be redeemed — for
        example because it's been fully spent, has expired, or doesn't
        belong to the basket's customer.
      operationId: createBasketCustomerCredit
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/CreateBasketCustomerCredit'
      responses:
        '200':
          description: The updated `Basket` with the customer credit applied.
          content:
            application/json:
              schema:
                title: CreateBasketCustomerCreditResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/customer-credits/{customerCredit}:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/customerCreditId'
    delete:
      summary: Remove a customer credit from a Basket
      description: |
        Detaches a previously-applied `CustomerCredit` from the basket.
        The credit's balance is restored to the customer and the
        basket's outstanding payment amount is recalculated.
      operationId: deleteBasketCustomerCredit
      tags:
        - Baskets
      responses:
        '204':
          description: The customer credit was successfully removed from the basket.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/intake-form:
    parameters:
      - $ref: '#/components/parameters/basketId'
    get:
      summary: Get intake form link
      tags:
        - Baskets
      description: |
        This endpoint returns the link which the customer should go to in order to fill out the intake form for the basket.
      operationId: getIntakeFormLink
      responses:
        '200':
          $ref: '#/components/responses/ShowIntakeFormLink'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/items/{item}:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/itemId'
    put:
      summary: Update a Basket item
      description: |
        Updates the schedule and/or quantity of an existing `BasketItem`.
        Passing `quantity: 0` removes the item from the basket — useful
        for quantity steppers in cart UIs.

        The `item_configuration` field accepts an arbitrary object of
        offering-specific options (e.g. `session_id` for a fitness
        session, `room_id` for a treatment, `flavour` for a product).
        Availability is re-checked on every update; if the new
        date/time isn't bookable the response is `400 Bad Request`.
      operationId: updateBasketItem
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/UpdateBasketItem'
      responses:
        '200':
          description: The updated `Basket`.
          content:
            application/json:
              schema:
                title: UpdateBasketItemResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove an item from a Basket
      description: |
        Removes a `BasketItem` from the basket. Any package items, guest
        assignments, and option budgets attached to the line are
        discarded. Reserved availability for the item is released
        immediately.
      operationId: deleteBasketItem
      tags:
        - Baskets
      responses:
        '200':
          description: The updated `Basket` with the item removed.
          content:
            application/json:
              schema:
                title: DeleteBasketItemResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/items/{item}/package-items:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/itemId'
    post:
      summary: Add a package item to a Basket item
      description: |
        Adds a child item to a package line item. Packages bundle
        several offerings together (e.g. a "Spa Day" comprising a
        treatment, lunch, and pool access). The `choice_id` selects
        which slot within the package is being filled and `option_id`
        selects which offering fills it.

        For scheduled package slots, pass `item_configuration` with
        `time`, `duration`, and (where relevant) `session_id` so the
        underlying availability check has the data it needs. Top-level
        `time` and `duration` parameters are accepted as a legacy
        alternative and will be merged into the configuration server-side.
      operationId: createBasketPackageItem
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/CreateBasketPackageItem'
      responses:
        '200':
          description: The updated `Basket` including the new package item.
          content:
            application/json:
              schema:
                title: CreateBasketPackageItemResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/items/{item}/package-items/{packageItem}:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/itemId'
      - $ref: '#/components/parameters/packageItemId'
    put:
      summary: Update a Basket package item
      description: |
        Updates the choice/option selection or schedule of a package's
        child item. Useful when a customer changes their mind about
        which treatment to take in a "Choose your own" package slot, or
        needs to shift the slot's start time.

        Availability is re-checked on every update.
      operationId: updateBasketPackageItem
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/UpdateBasketPackageItem'
      responses:
        '200':
          description: The updated `Basket`.
          content:
            application/json:
              schema:
                title: UpdateBasketPackageItemResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a Basket package item
      description: |
        Removes a child item from a package line. Any subsequent
        package items that depended on this slot (e.g. a follow-on
        treatment scheduled relative to it) may be removed too.
      operationId: deleteBasketPackageItem
      tags:
        - Baskets
      responses:
        '200':
          description: The updated `Basket` with the package item removed.
          content:
            application/json:
              schema:
                title: DeleteBasketPackageItemResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/payments:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Add a payment to a Basket
      description: |
        Attaches a payment intent or completed payment to the basket.
        Most commonly used to register a voucher or external-voucher
        payment alongside (or instead of) a card payment.

        Behaviour depends on `processor`:

        - `voucher` / `external_voucher` — redeems the supplied voucher
          against the basket immediately. The `amount` defaults to the
          outstanding submit amount when omitted; supplying a smaller
          `amount` lets a customer split-pay across multiple methods.
        - `stripe` — accepted for compatibility but treated as a no-op:
          Stripe payments are added automatically after the customer
          returns from the Stripe Checkout flow.

        Returns `400 Bad Request` when the amount exceeds what's
        outstanding, when the chosen processor is misconfigured, or
        when the payment can't be created (e.g. voucher already spent).
      operationId: createBasketPayment
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/CreateBasketPayment'
      responses:
        '200':
          description: The updated `Basket` with the new payment attached.
          content:
            application/json:
              schema:
                title: CreateBasketPaymentResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/payments/{payment}:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/parameters_paymentId'
    delete:
      summary: Remove a payment from a Basket
      description: |
        Detaches a `Payment` from the basket. Any voucher balance the
        payment was consuming is released back to the voucher, and the
        basket's outstanding submit amount is recalculated.

        Only valid while the basket is updatable — submitted baskets
        return `400 Bad Request`.
      operationId: deleteBasketPayment
      tags:
        - Baskets
      responses:
        '200':
          description: The updated `Basket` with the payment removed.
          content:
            application/json:
              schema:
                title: DeleteBasketPaymentResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/pre-submit:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Pre-submit validation for a Basket
      description: |
        Runs the same validation suite that `POST
        /shop/basket/{basketId}/submit` runs — checking availability,
        customer details, payment requirements, and integration
        pre-conditions — without committing the basket. The response is
        the latest basket payload, with any validation failures surfaced
        via the `submit_errors` collection.

        Call this immediately before the customer enters payment details
        so you can fail fast and avoid taking money for a basket that's
        going to be rejected on submit.

        Returns `400 Bad Request` if the basket can't even reach the
        payment step (e.g. an item is unavailable or a payment
        processor error occurred during pre-flight).
      operationId: actionPreSubmitBasket
      tags:
        - Baskets
      responses:
        '200':
          description: The basket after pre-submit validation has run.
          content:
            application/json:
              schema:
                title: PreSubmitBasketResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/reserve:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Reserve Basket items
      description: |
        Soft-holds availability for every item in the basket so the
        customer can complete payment without losing their slot. Reserved
        items expire after a short window (the response's
        `items_reserved_until` indicates the deadline) and are
        automatically released if the basket isn't submitted in time.

        A customer must be attached to the basket (`POST
        /shop/basket/{basketId}/customer`) before items can be reserved
        — call this immediately before sending the customer to the
        payment step.

        Returns `400 Bad Request` if one or more items have become
        unavailable since they were added; the response message
        identifies the conflict.
      operationId: actionReserveBasket
      tags:
        - Baskets
      responses:
        '200':
          description: The updated `Basket` with reservations in place.
          content:
            application/json:
              schema:
                title: ReserveBasketResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/basket/{basketId}/submit:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Submit a Basket
      description: |
        Finalises the basket and turns it into an `Order`. On success
        the basket transitions to `submitted`, an `Order` is created,
        appointments and area bookings are confirmed (or queued as
        enquiries depending on configuration), payments are captured or
        authorised, and confirmation email + SMS are sent to the
        customer.

        The endpoint is idempotent within a one-hour window for already
        submitted baskets — a re-submit returns the existing basket
        with the intake-form URL attached. Beyond the window, submitted
        baskets respond `404 Not Found`.

        You can optionally include `customer_id` or `email` (and the
        other guest-checkout fields) directly in the submit payload to
        set the customer in the same request — this delegates to the
        same logic as `POST /shop/basket/{basketId}/customer`.

        Returns `400 Bad Request` for any submit-time failure:
        unavailable items, validation errors, payment failures, or a
        lock timeout when another concurrent submit is in progress.
      operationId: actionSubmitBasket
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/SubmitBasket'
      responses:
        '200':
          description: The submitted `Basket` (with an attached intake-form URL when relevant).
          content:
            application/json:
              schema:
                title: SubmitBasketResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/update-guests:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Bulk update Basket guests
      description: |
        Replaces or upserts the basket's guest list in one call. Each
        entry can carry an `id` to update an existing guest in-place, or
        omit `id` to create a new guest. Pre-existing guests not
        referenced in the payload are left untouched.

        Use this after collecting guest details on a multi-guest booking
        journey — it's cheaper than issuing one mutation per guest and
        keeps the basket's totals consistent.
      operationId: actionBulkUpdateBasketGuests
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/BulkUpdateBasketGuests'
      responses:
        '200':
          description: The updated `Basket` with refreshed guest entries.
          content:
            application/json:
              schema:
                title: BulkUpdateBasketGuestsResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/vouchers:
    parameters:
      - $ref: '#/components/parameters/basketId'
    post:
      summary: Apply a voucher to a Basket
      description: |
        Redeems a `VoucherCode` against the basket as a payment method.
        Trybe-issued vouchers carry a remaining balance and are partially
        or fully applied to the basket total; external vouchers (from a
        third-party voucher integration) are validated with the provider
        and held against the basket until submit.

        Returns `400 Bad Request` if the voucher can't be redeemed (e.g.
        wrong site, expired, already fully spent, or the third-party
        provider returned an error).
      operationId: createBasketVoucher
      tags:
        - Baskets
      requestBody:
        $ref: '#/components/requestBodies/CreateBasketVoucher'
      responses:
        '200':
          description: The updated `Basket` with the voucher applied.
          content:
            application/json:
              schema:
                title: CreateBasketVoucherResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/Basket'
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/vouchers/{voucher}:
    parameters:
      - $ref: '#/components/parameters/basketId'
      - $ref: '#/components/parameters/parameters_voucherCodeId'
    delete:
      summary: Remove a voucher from a Basket
      description: |
        Detaches a previously-applied `VoucherCode` from the basket. Any
        balance the voucher was contributing is released back to the
        voucher and basket totals are recalculated.
      operationId: deleteBasketVoucher
      tags:
        - Baskets
      responses:
        '204':
          description: The voucher was successfully removed from the basket.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/bookable-areas:
    parameters:
      - $ref: '#/components/parameters/requiredSiteId'
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
    get:
      summary: List bookable areas
      description: |
        Returns a paginated list of `BookableArea`s at the given site,
        ordered by their `order` field then by name. Use this to populate
        a settings dashboard or a calendar resource picker.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listBookableAreas
      tags:
        - BookableAreas
      responses:
        '200':
          $ref: '#/components/responses/ListBookableAreas'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a bookable area
      description: |
        Creates a new `BookableArea` at the site identified by the
        `site_id` query parameter. The minimum body is `name` and
        `capacity`.

        Requires the `SETTINGS_MANAGE` permission on the site.
      operationId: createBookableArea
      tags:
        - BookableAreas
      requestBody:
        $ref: '#/components/requestBodies/CreateBookableArea'
      responses:
        '201':
          $ref: '#/components/responses/ShowBookableArea'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/bookable-areas/order:
    get:
      summary: List ordered bookable areas
      description: |
        Returns the site's `BookableArea`s in their current display
        order. Pair with `PUT /shop/bookable-areas/order` to power a
        drag-and-drop ordering UI.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listOrderedBookableAreas
      tags:
        - BookableAreas
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedBookableAreas'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update bookable area order
      description: |
        Replaces the display order of the site's `BookableArea`s. The
        order of `area_ids` in the body is the new order — element 0
        becomes `order=0`, element 1 becomes `order=1`, and so on.

        Requires the `SETTINGS_MANAGE` permission on the site.
      operationId: updateBookableAreaOrder
      tags:
        - BookableAreas
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: UpdateBookableAreaOrderRequest
              type: object
              additionalProperties: false
              required:
                - area_ids
                - site_id
              properties:
                area_ids:
                  type: array
                  description: |
                    Ordered list of bookable area IDs. Element 0 becomes
                    the first-displayed area.
                  items:
                    type: string
                    format: object-id
                site_id:
                  type: string
                  format: uuid
                  description: |
                    ID of the site whose area order is being updated.
                    The caller's API key must have access to this site.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedBookableAreas'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/bookable-areas/{bookableAreaId}:
    parameters:
      - $ref: '#/components/parameters/bookableAreaId'
    get:
      summary: Retrieve a bookable area
      description: |
        Returns the full `BookableArea` for the given ID.

        Requires the `RESERVATIONS_VIEW` permission on the area's site.
      operationId: getBookableArea
      tags:
        - BookableAreas
      responses:
        '200':
          $ref: '#/components/responses/ShowBookableArea'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a bookable area
      description: |
        Updates a `BookableArea`. The validator enforces the same shape
        as on create — `name` and `capacity` are required. Sending fewer
        fields than that returns 422.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      operationId: updateBookableArea
      tags:
        - BookableAreas
      requestBody:
        $ref: '#/components/requestBodies/UpdateBookableArea'
      responses:
        '200':
          $ref: '#/components/responses/ShowBookableArea'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a bookable area
      description: |
        Soft-deletes the bookable area. Existing area bookings are
        unaffected, but the area is removed from new-booking allocations
        and disassociated from any `AreaBookingType` it was attached to.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      operationId: deleteBookableArea
      tags:
        - BookableAreas
      responses:
        '204':
          description: Bookable area deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/bookable-areas/{bookableAreaId}/copy:
    parameters:
      - $ref: '#/components/parameters/bookableAreaId'
    post:
      summary: Duplicate a bookable area
      description: |
        Creates a copy of an existing `BookableArea` under the same site
        and organisation. Useful for seeding additional areas off an
        existing one — e.g. "Hot Tub 2" copied from "Hot Tub 1".

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      operationId: copyBookableArea
      tags:
        - BookableAreas
      requestBody:
        $ref: '#/components/requestBodies/CopyBookableArea'
      responses:
        '201':
          $ref: '#/components/responses/ShowBookableArea'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/bookable-areas/{bookableAreaId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/bookableAreaId'
    get:
      summary: List availability rules for a bookable area
      tags:
        - BookableAreas
      operationId: listBookableAreaAvailabilityRules
      description: |
        Returns all `AvailabilityRule`s configured on a `BookableArea`.
        Availability rules carve up the calendar into windows when the
        area can or cannot be booked — useful for blocking maintenance
        slots or restricting cabana hours.

        Any `is_available: false` rule overrides any `is_available: true`
        rule for the same time period.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      responses:
        '200':
          $ref: '#/components/responses/ListBookableAreaAvailabilityRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an availability rule for a bookable area
      tags:
        - BookableAreas
      operationId: createBookableAreaAvailabilityRule
      description: |
        Adds a new `AvailabilityRule` to a `BookableArea`. With
        `is_available: true` the rule opens new bookable windows; with
        `is_available: false` it blocks them. Omitting date/time/weekday
        filters means the rule applies always.

        `date_from` defaults to today in the area's timezone when omitted.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      requestBody:
        $ref: '#/components/requestBodies/CreateBookableAreaAvailabilityRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowBookableAreaAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/bookable-areas/{bookableAreaId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/bookableAreaId'
      - $ref: '#/components/parameters/availabilityRuleId'
    get:
      summary: Retrieve a bookable area availability rule
      tags:
        - BookableAreas
      operationId: getBookableAreaAvailabilityRule
      description: |
        Returns a single `AvailabilityRule` belonging to the given
        `BookableArea`.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowBookableAreaAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a bookable area availability rule
      tags:
        - BookableAreas
      operationId: updateBookableAreaAvailabilityRule
      description: |
        Updates an `AvailabilityRule` on a `BookableArea`. The server
        validates the same shape as on create, so `is_available` is
        required. Calendar availability is recomputed from the updated
        rule set.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateBookableAreaAvailabilityRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowBookableAreaAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a bookable area availability rule
      tags:
        - BookableAreas
      operationId: deleteBookableAreaAvailabilityRule
      description: |
        Removes an `AvailabilityRule` from a `BookableArea`. Calendar
        availability is recomputed from the remaining rules. Existing
        bookings are unaffected.

        Requires the `SETTINGS_MANAGE` permission on the area's site.
      responses:
        '204':
          description: Availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/course-types/{courseTypeId}:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
    get:
      summary: Retrieve a CourseType
      description: Use this endpoint to retrieve a `CourseType` offering type.
      operationId: getCourseType
      tags:
        - CourseTypes
      responses:
        '200':
          description: Successfully retrieved a `CourseType`.
          content:
            application/json:
              schema:
                title: ShowCourseType
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/CourseType'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a course type
      description: |
        Partially updates a `CourseType`. Every field is optional; only
        fields you send are written. Fields you omit retain their current
        values.

        If the course type does not yet have a `coupon_id` (legacy
        course types from earlier versions of the API), one is provisioned
        on first update so future redemptions can be tracked. The coupon's
        name is kept in sync with `<name> credit` automatically.

        Requires the `SETTINGS_MANAGE` permission on the course type's
        site.
      operationId: updateCourseType
      tags:
        - CourseTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateCourseType'
      responses:
        '200':
          $ref: '#/components/responses/ShowCourseTypeEnvelope'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a course type
      description: |
        Soft-deletes the course type. Existing course credits already
        sold under this type remain redeemable; the type itself is
        removed from new-sale flows. Use `POST .../restore` to bring it
        back.

        Requires the `SETTINGS_MANAGE` permission on the course type's
        site. No request body.
      operationId: deleteCourseType
      tags:
        - CourseTypes
      responses:
        '204':
          description: Course type deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/course-types/{courseTypeId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a CourseType
      description: Returns the localised `name`, `description`, `meta_title` and `meta_description` for the given locale.
      operationId: getCourseTypeLocaleStrings
      tags:
        - CourseTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowCourseTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a CourseType
      description: Sets the localised `name`, `description`, `meta_title` and/or `meta_description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateCourseTypeLocaleStrings
      tags:
        - CourseTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateCourseTypeLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateCourseTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/course-types/{courseTypeId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
    get:
      summary: List availability rules for a course type
      tags:
        - CourseTypes
      operationId: listCourseTypeAvailabilityRules
      description: |
        Returns all `AvailabilityRule`s configured on a `CourseType`. Rules
        define when this course type can be purchased — date ranges where
        it's available or explicitly unavailable.

        Rule semantics: any `is_available: false` rule overrides any
        `is_available: true` rule for the same time period (closed beats
        open).
      responses:
        '200':
          $ref: '#/components/responses/ListCourseTypeAvailabilityRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an availability rule for a course type
      tags:
        - CourseTypes
      operationId: createCourseTypeAvailabilityRule
      description: |
        Adds a new `AvailabilityRule` to a `CourseType`. Use to open
        bookable windows (`is_available: true`) or block existing ones
        (`is_available: false`). Course-type availability rules are
        simpler than appointment- or area-rule equivalents: only date
        filters, no time-of-day or weekday conditions.

        Requires the `update` permission on the parent course type
        (typically `SETTINGS_MANAGE` on the course type's site).
      requestBody:
        $ref: '#/components/requestBodies/CreateCourseTypeAvailabilityRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowCourseTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/course-types/{courseTypeId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
      - $ref: '#/components/parameters/availabilityRuleId'
    get:
      summary: Retrieve a course-type availability rule
      tags:
        - CourseTypes
      operationId: getCourseTypeAvailabilityRule
      description: Returns a single `AvailabilityRule` belonging to the given `CourseType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowCourseTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a course-type availability rule
      tags:
        - CourseTypes
      operationId: updateCourseTypeAvailabilityRule
      description: |
        Updates an `AvailabilityRule`. The server validates the same shape
        as on create, so `is_available` is required. Requires the `update`
        permission on the parent course type.
      requestBody:
        $ref: '#/components/requestBodies/UpdateCourseTypeAvailabilityRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowCourseTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a course-type availability rule
      tags:
        - CourseTypes
      operationId: deleteCourseTypeAvailabilityRule
      description: |
        Removes an `AvailabilityRule` from a `CourseType`. Existing
        bookings/redemptions are unaffected. Future availability is
        recomputed from whatever rules remain.
      responses:
        '204':
          description: Availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/course-types/{courseTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
    post:
      summary: Duplicate a course type
      description: |
        Creates a copy of an existing `CourseType` with new fields applied
        from the request body. `name` is required so the copy is
        distinguishable from the source. Fields you omit are inherited
        from the source.

        Requires the `SETTINGS_MANAGE` permission on the source course
        type's site.
      operationId: copyCourseType
      tags:
        - CourseTypes
      requestBody:
        $ref: '#/components/requestBodies/CopyCourseType'
      responses:
        '201':
          description: The course type was copied.
          content:
            application/json:
              schema:
                title: CopyCourseTypeResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/CourseType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/course-types/{courseTypeId}/price-rules:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
    get:
      summary: List price rules for a course type
      tags:
        - CourseTypes
      operationId: listCourseTypePriceRules
      description: |
        Returns all `PriceRule`s configured for a `CourseType`, filterable
        by date range. Course price rules let you charge different prices
        for the same course at different times — e.g. summer rates for a
        membership-credit course. Only date-range filters are supported
        (no time-of-day or weekday conditions). The first rule whose
        conditions match the time of sale wins.
      parameters:
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCourseTypePriceRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a price rule for a course type
      tags:
        - CourseTypes
      operationId: createCourseTypePriceRule
      description: |
        Adds a new `PriceRule` to a `CourseType`. Set `price` and optionally
        a `date_from`/`date_to` window. With no date filters the rule
        applies always — useful as the baseline price.

        When `offering_standard_price` is enabled for the site, the course type's
        `standard_price` must be set before a price rule can be created. A zero
        amount counts as set. Requires the `update` permission on the parent
        `CourseType` (typically `SETTINGS_MANAGE` on the course type's site).
      requestBody:
        $ref: '#/components/requestBodies/CreateCourseTypePriceRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowCourseTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/course-types/{courseTypeId}/price-rules/{priceRuleId}:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
      - $ref: '#/components/parameters/priceRuleId'
    get:
      summary: Retrieve a course-type price rule
      tags:
        - CourseTypes
      operationId: getCourseTypePriceRule
      description: Returns a single `PriceRule` belonging to the given `CourseType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowCourseTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a course-type price rule
      tags:
        - CourseTypes
      operationId: updateCourseTypePriceRule
      description: |
        Partially updates a `PriceRule` on a `CourseType`. All fields are
        optional. When `offering_standard_price` is enabled for the site, the
        course type's `standard_price` must be set before a price rule can be
        updated. A zero amount counts as set. Requires the `update` permission on
        the parent course type.
      requestBody:
        $ref: '#/components/requestBodies/UpdateCourseTypePriceRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowCourseTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a course-type price rule
      tags:
        - CourseTypes
      operationId: deleteCourseTypePriceRule
      description: |
        Removes a `PriceRule` from a `CourseType`. Past purchases priced
        under this rule are unaffected. Future sales reprice from whatever
        rules remain (falling back to the course type's base price if none
        apply). When `offering_standard_price` is enabled for the site, the
        course type's `standard_price` must be set before a price rule can be
        deleted. A zero amount counts as set.
      responses:
        '204':
          description: Price rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/course-types/{courseTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/courseTypeId'
    post:
      summary: Restore a deleted course type
      description: |
        Un-deletes a previously soft-deleted `CourseType`. The course type
        returns to its pre-deletion state, including underlying offering
        associations, quantity, and credit-validity rules. Existing
        purchases that contained the course remain unaffected.

        Requires the `SETTINGS_MANAGE` permission on the course type's
        site. No request body.
      operationId: restoreCourseType
      tags:
        - CourseTypes
      responses:
        '200':
          description: The course type was restored successfully.
          content:
            application/json:
              schema:
                title: RestoreCourseTypeResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/CourseType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/search:
    parameters:
      - $ref: '#/components/parameters/requiredSiteId'
      - $ref: '#/components/parameters/parameters_query-2'
      - $ref: '#/components/parameters/source'
      - $ref: '#/components/parameters/firstName'
      - $ref: '#/components/parameters/lastName'
      - $ref: '#/components/parameters/email'
    get:
      summary: Search for customers
      tags:
        - Customers
      operationId: actionCustomerSearch
      description: |
        Use this endpoint to search for customers.
      responses:
        '200':
          description: Customer search results
          $ref: '#/components/responses/CustomerSearchResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '422':
          description: The search query was invalid
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/{customerId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    delete:
      summary: Delete a Customer
      description: |
        Anonymises the given `Customer`. The customer record is retained for
        accounting and reporting purposes but personally identifiable
        information is scrubbed.
      tags:
        - Customers
      operationId: deleteCustomer
      responses:
        '204':
          description: The customer was successfully anonymised
        '400':
          description: The customer could not be anonymised
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/{customerId}/stats:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: Get stats for a single customer across the whole organisation
      tags:
        - Customers
      operationId: getCustomerStats
      description: |
        Use this endpoint to retrieve high-level stats for a single customer.
      responses:
        '200':
          description: Customer stats were found
          $ref: '#/components/responses/CustomerStatsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          description: The customer could not be found
          $ref: '#/components/responses/EntityNotFound'
  /shop/equipment:
    get:
      summary: List equipment
      description: |
        Returns a paginated list of `Equipment` configured at the given
        site. Use this to populate an admin equipment-management view, or
        to verify equipment IDs before assigning them to appointment types.

        Requires the `SETTINGS_VIEW` permission on the site.
      operationId: listEquipment
      tags:
        - Equipment
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListEquipment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create equipment
      description: |
        Creates a new `Equipment` record at a site. Once created, the
        equipment can be assigned to appointment types — bookings then
        only offer slots when at least one unit is free.

        Requires the `SETTINGS_MANAGE` permission on the target site.
      operationId: createEquipment
      tags:
        - Equipment
      requestBody:
        $ref: '#/components/requestBodies/CreateEquipment'
      responses:
        '201':
          $ref: '#/components/responses/ShowEquipment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/equipment/{equipmentId}:
    parameters:
      - $ref: '#/components/parameters/equipmentId'
    get:
      summary: Retrieve an equipment item
      description: Returns a single `Equipment` record by ID.
      operationId: getEquipment
      tags:
        - Equipment
      responses:
        '200':
          $ref: '#/components/responses/ShowEquipment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an equipment item
      description: |
        Partially updates an `Equipment` record. Every field is optional;
        only fields you send are written. Requires the `SETTINGS_MANAGE`
        permission on the equipment's current site (and the target site
        too, if `site_id` is changed).
      operationId: updateEquipment
      tags:
        - Equipment
      requestBody:
        $ref: '#/components/requestBodies/UpdateEquipment'
      responses:
        '200':
          $ref: '#/components/responses/ShowEquipment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an equipment item
      description: |
        Removes an `Equipment` record. Appointment types still referencing
        the equipment retain the (now-invalid) ID until their next update —
        the booking engine treats missing equipment as unavailable, so
        deleting an in-use equipment item effectively makes those
        appointment types unbookable.

        Requires the `SETTINGS_MANAGE` permission on the equipment's site.
      operationId: deleteEquipment
      tags:
        - Equipment
      responses:
        '204':
          description: Equipment deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/esc-pos-connectors/{escPosConnector}:
    parameters:
      - $ref: '#/components/parameters/escPosConnector'
  /shop/discount-types:
    get:
      summary: List DiscountTypes
      tags:
        - DiscountTypes
      operationId: listDiscountTypes
      description: |
        This endpoint lists all the `DiscountTypes` which are associated to the provided site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-3'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/parameters_query-3'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/applicableFor'
      responses:
        '200':
          $ref: '#/components/responses/ListDiscountTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a DiscountType
      tags:
        - DiscountTypes
      operationId: createDiscountType
      description: |
        Use this endpoint to create a new `DiscountType` (or Promo Code).
        You can choose where a `DiscountType` can be applied, i.e. in the app only, on the booking engine only, or on both.
        When configured for in-app use only, the `DiscountType` has fewer customisable options and can only be applied to an order by the spa.
        When configured for use on the booking engine only, the `DiscountType` is a Promo Code which the customer enters for a discount on their order.
        When configured for use on both the app and the booking engine, the spa can enter a Promo Code on an order on the customer's behalf.
      requestBody:
        $ref: '#/components/requestBodies/CreateDiscountType'
      responses:
        '201':
          $ref: '#/components/responses/ShowDiscountType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/discount-types/order:
    get:
      summary: Order DiscountTypes
      tags:
        - DiscountTypes
      operationId: listOrderedDiscountTypes
      description: |
        This endpoint returns an ordered list of all the `DiscountTypes` which are associated with the provided site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-3'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedDiscountTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    put:
      summary: Update the DiscountTypes order
      tags:
        - DiscountTypes
      operationId: updateDiscountTypeOrder
      description: |
        This endpoint updates the order of the `DiscountTypes` which are associated with the provided site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateDiscountTypeOrder'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedDiscountTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/discount-types/{discountType}:
    parameters:
      - $ref: '#/components/parameters/discountType'
    get:
      summary: Show a DiscountType
      description: |
        Retrieves a `DiscountType` by ID.
      tags:
        - DiscountTypes
      operationId: getDiscountType
      responses:
        '200':
          $ref: '#/components/responses/ShowDiscountType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a DiscountType
      description: |
        Updates a `DiscountType` by ID.
      tags:
        - DiscountTypes
      operationId: updateDiscountType
      requestBody:
        $ref: '#/components/requestBodies/UpdateDiscountType'
      responses:
        '200':
          $ref: '#/components/responses/ShowDiscountType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a DiscountType
      description: |
        Soft deletes a `DiscountType` by ID.
      tags:
        - DiscountTypes
      operationId: deleteDiscountType
      responses:
        '204':
          description: The discount type was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/discount-types/{discountType}/copy:
    parameters:
      - $ref: '#/components/parameters/discountType'
    post:
      summary: Copy a DiscountType
      description: |
        Copies an existing `DiscountType` by ID.
      tags:
        - DiscountTypes
      operationId: actionDiscountType
      requestBody:
        $ref: '#/components/requestBodies/CopyDiscountType'
      responses:
        '200':
          $ref: '#/components/responses/ShowDiscountType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/discount-types/{discountType}/restore:
    parameters:
      - $ref: '#/components/parameters/discountType'
    post:
      summary: Restore a DiscountType
      description: |
        Restores an archived (soft-deleted) `DiscountType` by ID.
      tags:
        - DiscountTypes
      operationId: restoreDiscountType
      responses:
        '200':
          $ref: '#/components/responses/ShowDiscountType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/external-id-types:
    get:
      summary: List external ID types
      tags:
        - ExternalIdTypes
      operationId: listExternalIdTypes
      description: |
        This endpoint lists all the `ExternalIdType`s which are associated with the provided site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-4'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListExternalIdTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a new external ID type
      tags:
        - ExternalIdTypes
      operationId: createExternalIdType
      description: |
        Use this endpoint to create a new `ExternalIdType`.
      requestBody:
        $ref: '#/components/requestBodies/CreateExternalIdType'
      responses:
        '201':
          $ref: '#/components/responses/ShowExternalIdType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/external-id-types/{externalIdType}:
    parameters:
      - $ref: '#/components/parameters/externalIdType'
    get:
      summary: Show an external ID type
      description: |
        Retrieves an `ExternalIdType` by ID.
      tags:
        - ExternalIdTypes
      operationId: getExternalIdType
      responses:
        '200':
          $ref: '#/components/responses/ShowExternalIdType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an external ID type
      description: |
        Updates an `ExternalIdType` by ID.
      tags:
        - ExternalIdTypes
      operationId: updateExternalIdType
      requestBody:
        $ref: '#/components/requestBodies/UpdateExternalIdType'
      responses:
        '200':
          $ref: '#/components/responses/ShowExternalIdType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive an external ID type
      description: |
        Soft deletes an `ExternalId` by ID.
      tags:
        - ExternalIdTypes
      operationId: deleteExternalIdType
      responses:
        '204':
          description: The external ID type was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/external-id-types/{externalIdType}/restore:
    parameters:
      - $ref: '#/components/parameters/externalIdType'
    post:
      summary: Restore an external id
      description: |
        Restores an archived (soft-deleted) `ExternalIdType` by ID.
      tags:
        - ExternalIdTypes
      operationId: restoreExternalIdType
      responses:
        '200':
          $ref: '#/components/responses/ShowExternalIdType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/external-id-types/{externalIdType}/sites:
    parameters:
      - $ref: '#/components/parameters/externalIdType'
    put:
      summary: Add a site to an external ID type
      description: |
        Enables the `ExternalIdType` for the given site.
      tags:
        - ExternalIdTypes
      operationId: createExternalIdTypeSite
      requestBody:
        $ref: '#/components/requestBodies/AddExternalIdTypeSite'
      responses:
        '200':
          $ref: '#/components/responses/ShowExternalIdType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/external-id-types/{externalIdType}/sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/externalIdType'
      - $ref: '#/components/parameters/parameters_siteId-5'
    delete:
      summary: Remove a site from an external ID type
      description: |
        Disables the the `ExternalIdType` for the given site.
      tags:
        - ExternalIdTypes
      operationId: deleteExternalIdTypeSite
      responses:
        '200':
          $ref: '#/components/responses/ShowExternalIdType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/hotel-room-types:
    get:
      summary: List hotel room types
      operationId: listHotelRoomTypes
      tags:
        - HotelRoomTypes
      description: |
        Use this endpoint to retrieve a list of hotel room types for a site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-6'
        - $ref: '#/components/parameters/externalSource'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListHotelRoomTypesResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/hotel-room-types/{hotelRoomTypeId}:
    parameters:
      - $ref: '#/components/parameters/hotelRoomTypeId'
    get:
      summary: Retrieve a single table reservation type
      operationId: getHotelRoomType
      tags:
        - HotelRoomTypes
      description: |
        Use this endpoint to retrieve a single table reservation type.
      responses:
        '200':
          $ref: '#/components/responses/HotelRoomTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/item-availability/appointment-enquiries/{appointmentTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_appointmentTypeId'
    get:
      summary: Check ability to enquire at the given times
      tags:
        - Availability
      description: Use this endpoint to check availability for an appointment enquiry
      operationId: actionCheckAppointmentEnquiryAvailability
      parameters:
        - $ref: '#/components/parameters/dateTimeFrom'
        - $ref: '#/components/parameters/dateTimeTo'
      responses:
        '200':
          $ref: '#/components/responses/AppointmentEnquiryAvailabilityResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/item-availability/table-reservation-slots/{tableReservationTypeId}:
    parameters:
      - $ref: '#/components/parameters/tableReservationTypeId'
    get:
      summary: Get available table reservation slots on a single date.
      tags:
        - OfferingAvailability
      operationId: getTableReservationSlots
      description: |
        This endpoint retrieves a list of slots for the reservation type on the given date.
      parameters:
        - $ref: '#/components/parameters/parameters_date-2'
        - $ref: '#/components/parameters/numGuests'
      responses:
        '200':
          $ref: '#/components/responses/TableReservationSlots'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/imports/{importId}:
    parameters:
      - $ref: '#/components/parameters/importId'
  /shop/imports/{importId}/rows:
    parameters:
      - $ref: '#/components/parameters/importId'
  /shop/imports/{importId}/rows/queue:
    parameters:
      - $ref: '#/components/parameters/importId'
  /shop/imports/{importId}/start:
    parameters:
      - $ref: '#/components/parameters/importId'
  /shop/imports/{importId}/reupload:
    parameters:
      - $ref: '#/components/parameters/importId'
  /shop/imports/{importId}/rollback:
    parameters:
      - $ref: '#/components/parameters/importId'
  /shop/intake-form-sections:
    get:
      summary: List intake form sections
      description: Use this endpoint to return a paginated list of `IntakeFormSection`s.
      operationId: listIntakeFormSections
      tags:
        - IntakeForms
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/type'
      responses:
        '200':
          description: A paginated list of `IntakeFormSection`s.
          content:
            application/json:
              schema:
                title: ListIntakeFormSectionsResponse
                type: object
                additionalProperties: false
                allOf:
                  - $ref: '#/components/schemas/Pagination'
                  - title: ListIntakeFormSectionsResponseData
                    type: object
                    additionalProperties: false
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/IntakeFormSection'
                    required:
                      - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create an IntakeFormSection
      description: Use this endpoint to create a new `IntakeFormSection`.
      operationId: createIntakeFormSection
      tags:
        - IntakeForms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: CreateIntakeFormSection
              type: object
              additionalProperties: false
              properties:
                description:
                  type: string
                  maxLength: 255
                  description: |
                    Admin-facing description of what this intake form section
                    captures. Visible in the questionnaire builder but not shown
                    to customers.
                  example: Pre-treatment health questions and consent
                intro_text:
                  type: string
                  nullable: true
                  description: |
                    Optional rich-text shown to the customer at the top of the
                    section, before the questions. Markdown is rendered.
                  example: |
                    Please answer honestly — these questions help us tailor your
                    treatment safely.
                offerings:
                  type: array
                  description: |
                    Offerings this intake form section is attached to. When a
                    customer books one of these offerings, the section is
                    surfaced in the intake flow.
                  items:
                    $ref: '#/components/schemas/OfferingIdentifier'
                outro_text:
                  type: string
                  nullable: true
                  description: |
                    Optional rich-text shown to the customer at the foot of the
                    section, after the questions. Useful for thank-yous or
                    follow-up instructions.
                  example: |
                    Thank you. Please proceed to checkout when you're ready.
                site_id:
                  type: string
                  format: uuid
                  description: ID of the site this intake form section belongs to.
                title:
                  type: string
                  maxLength: 255
                  description: |
                    Customer-facing heading for the section. Plain text only —
                    HTML tags are stripped.
                  example: Health Declaration
                type:
                  type: string
                  nullable: true
                  description: |
                    Optional category flag. `mandatory` marks the section as
                    non-skippable in the intake flow — the customer must
                    complete it before checkout. Null (the default) makes the
                    section advisory.
                  enum:
                    - mandatory
              required:
                - site_id
                - title
      responses:
        '201':
          description: Successfully created an `IntakeFormSection`.
          content:
            application/json:
              schema:
                title: CreateIntakeFormSectionResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/IntakeFormSection'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/intake-form-sections/order:
    get:
      summary: List orderable IntakeFormSections
      description: Returns a list of orderable `IntakeFormSection`s for the given site.
      operationId: listOrderableIntakeFormSections
      tags:
        - IntakeForms
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/OrderableIntakeFormSections'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    put:
      summary: Update orderable IntakeFormSections
      description: Updates the order of `IntakeFormSection`s for the given site.
      operationId: updateOrderableIntakeFormSections
      tags:
        - IntakeForms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: UpdateOrderableIntakeFormSectionsRequest
              type: object
              additionalProperties: false
              properties:
                intake_form_section_ids:
                  type: array
                  items:
                    type: string
                    format: object-id
                site_id:
                  type: string
                  format: uuid
                  description: |
                    ID of the site whose intake form section order is being
                    updated. The caller's API key must have access to this
                    site.
              required:
                - intake_form_section_ids
                - site_id
      responses:
        '200':
          $ref: '#/components/responses/OrderableIntakeFormSections'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/intake-form-sections/{intakeFormSectionId}:
    parameters:
      - $ref: '#/components/parameters/intakeFormSectionId'
    get:
      summary: Retrieve an IntakeFormSection
      description: Returns a paginated list of intake form sections for the authenticated site.
      operationId: getIntakeFormSection
      tags:
        - IntakeForms
      responses:
        '200':
          description: Successfully retrieved `IntakeFormSection`.
          content:
            application/json:
              schema:
                title: ShowIntakeFormSectionResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/IntakeFormSection'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an IntakeFormSection
      description: Use this endpoint to update an `IntakeFormSection`.
      operationId: updateIntakeFormSection
      tags:
        - IntakeForms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: UpdateIntakeFormSectionRequest
              type: object
              additionalProperties: false
              properties:
                description:
                  type: string
                  maxLength: 255
                  description: |
                    Admin-facing description of what this intake form section
                    captures. Visible in the questionnaire builder but not shown
                    to customers.
                  example: Pre-treatment health questions and consent
                intro_text:
                  type: string
                  nullable: true
                  description: |
                    Optional rich-text shown to the customer at the top of the
                    section. Markdown is rendered.
                  example: |
                    Please answer honestly — these questions help us tailor your
                    treatment safely.
                offerings:
                  type: array
                  description: Offerings this intake form section is attached to.
                  items:
                    $ref: '#/components/schemas/OfferingIdentifier'
                order:
                  type: integer
                  description: |
                    Zero-based display order of this section relative to others
                    on the same form. Lower values appear first.
                  example: 0
                outro_text:
                  type: string
                  nullable: true
                  description: |
                    Optional rich-text shown to the customer at the foot of the
                    section, after the questions.
                  example: |
                    Thank you. Please proceed to checkout when you're ready.
                title:
                  type: string
                  maxLength: 255
                  description: |
                    Customer-facing heading for the section. Plain text only —
                    HTML tags are stripped.
                  example: Health Declaration
                type:
                  type: string
                  nullable: true
                  description: |
                    Optional category flag. `mandatory` marks the section as
                    non-skippable in the intake flow — the customer must
                    complete it before checkout. Null (the default) makes the
                    section advisory.
                  enum:
                    - mandatory
      responses:
        '200':
          description: Successfully updated an `IntakeFormSection`.
          content:
            application/json:
              schema:
                title: UpdateIntakeFormSectionResponse
                allOf:
                  - $ref: '#/components/schemas/201-content-application~1json-schema'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an IntakeFormSection
      description: Use this endpoint to delete an `IntakeFormSection`.
      operationId: deleteIntakeFormSection
      tags:
        - IntakeForms
      responses:
        '204':
          description: Successfully deleted the `IntakeFormSection`.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/intake-form-sections/{intakeFormSectionId}/questions:
    parameters:
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
      - $ref: '#/components/parameters/intakeFormSectionId'
      - $ref: '#/components/parameters/parameters_siteId-7'
    get:
      summary: List IntakeFormQuestions
      description: Use this endpoint to list paginated `IntakeFormQuestion`s for an `IntakeFormSection`.
      operationId: listIntakeFormQuestions
      tags:
        - IntakeForms
      responses:
        '200':
          description: Successfully retrieved `IntakeFormQuestion`s.
          content:
            application/json:
              schema:
                title: ListIntakeFormQuestionsResponse
                type: object
                additionalProperties: false
                allOf:
                  - $ref: '#/components/schemas/Pagination'
                  - title: ListIntakeFormQuestionsResponseData
                    type: object
                    additionalProperties: false
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/IntakeFormQuestion'
                    required:
                      - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an IntakeFormQuestion
      description: |
        Creates a new `IntakeFormQuestion` in the parent section. The new
        question is appended to the end of the section's question list;
        use the `intake-form-sections/{intakeFormSectionId}/questions/order`
        endpoint to reposition it afterwards.

        `question` and `type` are required. `multiple_choice` questions
        additionally require at least two entries in
        `multiple_choice_answers`. `terms_statement` HTML is sanitised
        against the site's allowed-tag list before persisting.

        Requires the `SETTINGS_MANAGE` permission on the section's site.
      operationId: createIntakeFormQuestion
      tags:
        - IntakeForms
      requestBody:
        $ref: '#/components/requestBodies/CreateIntakeFormQuestion'
      responses:
        '201':
          description: The question was created successfully.
          content:
            application/json:
              schema:
                title: ShowIntakeFormQuestion
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/IntakeFormQuestion'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/intake-form-sections/{intakeFormSectionId}/questions/order:
    parameters:
      - $ref: '#/components/parameters/intakeFormSectionId'
    put:
      summary: Order IntakeFormQuestions
      description: Use this endpoint to order `IntakeFormQuestion`s for an `IntakeFormSection`.
      operationId: updateIntakeFormQuestionsOrder
      tags:
        - IntakeForms
      requestBody:
        $ref: '#/components/requestBodies/OrderIntakeFormQuestions'
      responses:
        '200':
          description: Successfully ordered `IntakeFormQuestion`s.
          content:
            application/json:
              schema:
                title: OrderIntakeFormQuestionsResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/IntakeFormQuestion'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/membership-types/{siteId}/{membershipTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-8'
      - $ref: '#/components/parameters/membershipTypeId'
  /shop/offering-search:
    get:
      summary: Search for offerings
      description: Use this endpoint to search for different offering types.
      operationId: listOfferings
      tags:
        - Offerings
      parameters:
        - $ref: '#/components/parameters/parameters_offeringType'
        - $ref: '#/components/parameters/parameters_practitionerId-2'
        - $ref: '#/components/parameters/parameters_query-4'
        - $ref: '#/components/parameters/parameters_siteId-9'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_sort'
      responses:
        '200':
          description: Successfully retrieved offerings.
          content:
            application/json:
              schema:
                title: ListOfferingsResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Offering'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                required:
                  - data
                  - meta
                  - links
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/packages:
    parameters:
      - $ref: '#/components/parameters/requiredSiteId'
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
      - $ref: '#/components/parameters/archivedQuery'
      - $ref: '#/components/parameters/parameters_categoryId-2'
      - $ref: '#/components/parameters/includeOptionOfferings'
    get:
      summary: List packages
      description: |
        Returns a paginated list of `Package`s configured at the given site,
        ordered by name. Use this to power a settings dashboard or to populate
        a shopfront browse page. The list includes archived (soft-deleted)
        packages only when `archived=true` is passed.

        Requires the `RESERVATIONS_VIEW` permission on the site. Pass
        `include_option_offerings=true` to embed each item choice's option
        offering details (helpful when rendering the package contents
        inline).
      operationId: listPackages
      tags:
        - Packages
      responses:
        '200':
          $ref: '#/components/responses/ListPackages'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a package
      description: |
        Creates a new `Package` at the given site. The minimum body is
        `name` + `site_id`; everything else has sensible defaults.
        Requires the `SETTINGS_MANAGE` permission on `site_id`.

        Server-side behaviour worth noting:
        - `separate_couples_package_choices` is forced to `false` unless
          both `min_guests` and `max_guests` equal `2`.
        - `permitted_membership_type_ids` is filtered to membership types
          within the site's brand; others are silently dropped.
        - When `overnight_package_config.enabled=true`, both `rate_id` and
          `num_nights` are required — otherwise the request fails with 422.
        - `organisation_id` defaults to the caller's primary organisation
          when omitted.
      operationId: createPackage
      tags:
        - Packages
      requestBody:
        $ref: '#/components/requestBodies/CreatePackage'
      responses:
        '201':
          $ref: '#/components/responses/ShowPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/basketItemId'
    get:
      summary: Retrieve a Package
      description: Use this endpoint to retrieve a single `Package` model.
      operationId: getPackage
      tags:
        - Packages
      responses:
        '200':
          description: The `Package` was successfully retrieved.
          content:
            application/json:
              schema:
                title: ShowPackageResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Package'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a package
      description: |
        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.
      operationId: updatePackage
      tags:
        - Packages
      requestBody:
        $ref: '#/components/requestBodies/UpdatePackage'
      responses:
        '200':
          $ref: '#/components/responses/ShowPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a package
      description: |
        Soft-deletes the package. Existing orders containing it are
        unaffected; the package is removed from new-booking flows. Use
        `POST .../restore` to bring it back.

        Requires the `SETTINGS_MANAGE` permission on the package's site.
      operationId: deletePackage
      tags:
        - Packages
      responses:
        '204':
          description: Package deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/packages/{packageId}/copy:
    parameters:
      - $ref: '#/components/parameters/packageId'
    post:
      summary: Duplicate a package
      description: |
        Creates a copy of an existing `Package` with new fields applied from
        the request body. Useful when seeding a new offering off an existing
        one rather than building from scratch. The new package is created
        under the same site and organisation as the original; fields not
        listed in the body are inherited from the source unchanged.

        Requires the `SETTINGS_MANAGE` permission on the original package's
        site. As with create/update, `separate_couples_package_choices` is
        forced to `false` unless both `min_guests` and `max_guests` equal
        `2`, and `overnight_package_config.enabled=true` requires `rate_id`
        and `num_nights`.
      operationId: copyPackage
      tags:
        - Packages
      requestBody:
        $ref: '#/components/requestBodies/CopyPackage'
      responses:
        '201':
          $ref: '#/components/responses/ShowPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/restore:
    parameters:
      - $ref: '#/components/parameters/packageId'
    post:
      summary: Restore a deleted package
      description: |
        Un-deletes a previously soft-deleted `Package`. The package returns
        to its pre-deletion state, including price, item choices,
        availability rules, and overnight configuration. Existing orders
        that contained the package remain unaffected.

        Requires the `SETTINGS_MANAGE` permission on the package's site.
        No request body.
      operationId: restorePackage
      tags:
        - Packages
      responses:
        '200':
          description: The package was restored successfully.
          content:
            application/json:
              schema:
                title: RestorePackageResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Package'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/packages/{packageId}/suggest-description:
    parameters:
      - $ref: '#/components/parameters/packageId'
  /shop/packages/{packageId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a Package
      description: Returns the localised `name`, `description`, `meta_title` and `meta_description` for the given locale.
      operationId: getPackageLocaleStrings
      tags:
        - Packages
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a Package
      description: Sets the localised `name`, `description`, `meta_title` and/or `meta_description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updatePackageLocaleStrings
      tags:
        - Packages
      requestBody:
        $ref: '#/components/requestBodies/UpdatePackageLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdatePackageLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/item-choices/{itemChoiceId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/itemChoiceId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a Package Item Choice
      description: Returns the localised `name` and `description` for the given locale.
      operationId: getPackageItemChoiceLocaleStrings
      tags:
        - Packages
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageItemChoiceLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a Package Item Choice
      description: Sets the localised `name` and/or `description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updatePackageItemChoiceLocaleStrings
      tags:
        - Packages
      requestBody:
        $ref: '#/components/requestBodies/UpdatePackageItemChoiceLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdatePackageItemChoiceLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/premier-core-mappings/{mappingId}:
    parameters:
      - $ref: '#/components/parameters/mappingId'
  /shop/premier-core-mappings/{mappingId}/update-line:
    parameters:
      - $ref: '#/components/parameters/mappingId'
  /shop/premier-core-mappings/{mappingId}/appointment-types:
    parameters:
      - $ref: '#/components/parameters/mappingId'
  /shop/premier-core-mappings/{mappingId}/facility-appointment-types:
    parameters:
      - $ref: '#/components/parameters/mappingId'
  /shop/premier-core-mappings/{mappingId}/package-types:
    parameters:
      - $ref: '#/components/parameters/mappingId'
  /shop/products:
    get:
      summary: List products
      tags:
        - Products
      operationId: getProducts
      description: |
        List the retail products available across the sites the caller's API
        key can access. Results are paginated and support filtering by free-text
        query, exact product code and inventory category. Use the show endpoint
        to retrieve the full product detail for any item returned here.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_query-5'
        - $ref: '#/components/parameters/productCode'
        - $ref: '#/components/parameters/inventoryCategoryId'
      responses:
        '200':
          $ref: '#/components/responses/ListProductsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a product
      tags:
        - Products
      operationId: createProduct
      description: |
        Create a new product. Requires the `SETTINGS_MANAGE` permission.
      requestBody:
        $ref: '#/components/requestBodies/CreateProduct'
      responses:
        '201':
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/products/{productId}:
    parameters:
      - $ref: '#/components/parameters/productId'
        required: true
    get:
      summary: Get a product
      tags:
        - Products
      operationId: getProduct
      description: |
        Fetch the full record for a single retail product, including its
        inventory link, pricing and metadata. Returns 404 if the ID is not
        visible to the caller's site scope.
      responses:
        '200':
          description: Product retrieved successfully
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a product
      tags:
        - Products
      operationId: updateProduct
      description: |
        Patch the editable fields on a retail product (e.g. product code,
        linked inventory product). Requires the `SETTINGS_MANAGE` permission;
        fields omitted from the body are left untouched.
      requestBody:
        $ref: '#/components/requestBodies/UpdateProduct'
      responses:
        '200':
          description: Product updated successfully
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a product
      tags:
        - Products
      operationId: deleteProduct
      description: |
        Soft-deletes a retail product. The product is hidden from the
        storefront and cannot be added to new baskets; existing orders that
        already contain the product are unaffected. Use
        `POST /shop/products/{productId}/restore` to bring a deleted product
        back.
      responses:
        '204':
          description: The product was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/products/{productId}/copy:
    parameters:
      - $ref: '#/components/parameters/productId'
    post:
      summary: Duplicate a product
      description: |
        Creates a copy of an existing `Product` with new fields applied
        from the request body. Useful when seeding a new product off an
        existing one rather than building from scratch.

        Requires the `SETTINGS_MANAGE` permission on the original product's
        site. The new product is created at the same site as the source.
      operationId: copyProduct
      tags:
        - Products
      requestBody:
        $ref: '#/components/requestBodies/CopyProduct'
      responses:
        '201':
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/products/{productId}/price-rules:
    parameters:
      - $ref: '#/components/parameters/productId'
    get:
      summary: List price rules for a product
      tags:
        - Products
      operationId: listProductPriceRules
      description: |
        Returns all `PriceRule`s configured for the given `Product`,
        filterable by date range. Product price rules let you charge
        different prices for the same product at different times — e.g.
        seasonal promotions, peak vs off-peak. The first rule whose
        conditions match the time of sale wins.

        Product price rules are simpler than appointment/session
        equivalents: they only support date-range filters (no time-of-day
        or weekday conditions).
      parameters:
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListProductPriceRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a price rule for a product
      tags:
        - Products
      operationId: createProductPriceRule
      description: |
        Adds a new `PriceRule` to a `Product`. Set `price` and optionally a
        `date_from`/`date_to` window. With no date filters the rule
        applies always — useful as a fallback baseline price.

        When `offering_standard_price` is enabled for the site, the product's
        `standard_price` must be set before a price rule can be created. A zero
        amount counts as set. Requires the `update` permission on the parent
        `Product` (typically `SETTINGS_MANAGE` on the product's site).
      requestBody:
        $ref: '#/components/requestBodies/CreateProductPriceRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowProductPriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/products/{productId}/price-rules/{priceRuleId}:
    parameters:
      - $ref: '#/components/parameters/productId'
      - $ref: '#/components/parameters/priceRuleId'
    get:
      summary: Retrieve a product price rule
      tags:
        - Products
      operationId: getProductPriceRule
      description: Returns a single `PriceRule` belonging to the given `Product`.
      responses:
        '200':
          $ref: '#/components/responses/ShowProductPriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a product price rule
      tags:
        - Products
      operationId: updateProductPriceRule
      description: |
        Partially updates a `PriceRule` on a `Product`. Every field is optional.
        When `offering_standard_price` is enabled for the site, the product's
        `standard_price` must be set before a price rule can be updated. A zero
        amount counts as set. Requires the `update` permission on the parent
        product.
      requestBody:
        $ref: '#/components/requestBodies/UpdateProductPriceRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowProductPriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a product price rule
      tags:
        - Products
      operationId: deleteProductPriceRule
      description: |
        Removes a `PriceRule` from a `Product`. Past orders already priced
        under this rule are unaffected — they retain the price set at
        order time. Future sales are repriced from whatever rules remain
        (falling back to the product's base price if none apply). When
        `offering_standard_price` is enabled for the site, the product's
        `standard_price` must be set before a price rule can be deleted. A zero
        amount counts as set.
      responses:
        '204':
          description: Price rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/products/{productId}/restore:
    parameters:
      - $ref: '#/components/parameters/productId'
    post:
      summary: Restore a deleted product
      description: |
        Un-deletes a previously soft-deleted `Product`. The product returns
        to its pre-deletion state, including price, inventory associations,
        and categories. Existing orders containing the product remain
        unaffected.

        Requires the `SETTINGS_MANAGE` permission on the product's site.
        No request body.
      operationId: restoreProduct
      tags:
        - Products
      responses:
        '200':
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/products/{productId}/suggest-description:
    parameters:
      - $ref: '#/components/parameters/productId'
    post:
      summary: Suggest description
      tags:
        - Products
      operationId: actionSuggestDescriptionForProduct
      description: |
        Use this endpoint to suggest a description for a `Product` using Trybe Intelligence.
      requestBody:
        $ref: '#/components/requestBodies/SuggestDescription'
      responses:
        '200':
          $ref: '#/components/responses/SuggestedDescription'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/products/{productId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/productId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a Product
      description: Returns the localised `name` and `description` for the given locale.
      operationId: getProductLocaleStrings
      tags:
        - Products
      responses:
        '200':
          $ref: '#/components/responses/ShowProductLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a Product
      description: Sets the localised `name` and/or `description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateProductLocaleStrings
      tags:
        - Products
      requestBody:
        $ref: '#/components/requestBodies/UpdateProductLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateProductLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/rooms:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId'
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
    get:
      summary: List rooms
      description: |
        Returns a paginated list of `Room`s the caller can see, ordered by
        their `order` field then by name. Filter to a single site with
        `site_id`; omit it to list every room in every site the caller has
        access to.

        Requires the `RESERVATIONS_VIEW` permission on the requested site.
      operationId: listRooms
      tags:
        - Rooms
      responses:
        '200':
          $ref: '#/components/responses/ListRooms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a room
      description: |
        Creates a new `Room` at the given site. The minimum body is
        `name`, `capacity`, and `site_id`. The room initially follows the
        site's opening hours; pass `use_custom_opening_hours = true`
        together with `availability_rules` to override.

        Requires the `SETTINGS_MANAGE` permission on the room's site.
      operationId: createRoom
      tags:
        - Rooms
      requestBody:
        $ref: '#/components/requestBodies/CreateRoom'
      responses:
        '201':
          $ref: '#/components/responses/ShowRoom'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/rooms/order:
    get:
      summary: List ordered rooms
      description: |
        Returns the site's `Room`s in their current display order. Used
        together with `PUT /shop/rooms/order` to power a drag-and-drop
        ordering UI in the admin panel.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listOrderedRooms
      tags:
        - Rooms
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedRooms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update room order
      description: |
        Replaces the display order of the site's `Room`s. The order of
        `room_ids` in the body is the new order — element 0 becomes
        `order=0`, element 1 becomes `order=1`, and so on.

        Requires the `SETTINGS_MANAGE` permission on the site.
      operationId: updateRoomOrder
      tags:
        - Rooms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: UpdateRoomOrderRequest
              type: object
              additionalProperties: false
              required:
                - room_ids
                - site_id
              properties:
                room_ids:
                  type: array
                  description: |
                    Ordered list of room IDs. Element 0 becomes the
                    first-displayed room, element 1 the second, and so on.
                  items:
                    type: string
                    format: object-id
                site_id:
                  type: string
                  format: uuid
                  description: |
                    ID of the site whose room order is being updated. The
                    caller's API key must have access to this site.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedRooms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/rooms/{roomId}:
    parameters:
      - $ref: '#/components/parameters/parameters_roomId'
    get:
      summary: Retrieve a room
      description: |
        Returns the full `Room` for the given ID. Use this to populate an
        admin edit screen or to look up the room's capacity and
        availability when checking schedules.

        Requires the `RESERVATIONS_VIEW` permission on the room's site.
      operationId: getRoom
      tags:
        - Rooms
      responses:
        '200':
          $ref: '#/components/responses/ShowRoom'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a room
      description: |
        Partially updates a `Room`. Every field is optional; only fields
        you send are written. Sending an empty `availability_rules` array
        clears the room's custom availability (server normalises it to
        `null`).

        Requires the `SETTINGS_MANAGE` permission on the room's site.
      operationId: updateRoom
      tags:
        - Rooms
      requestBody:
        $ref: '#/components/requestBodies/UpdateRoom'
      responses:
        '200':
          $ref: '#/components/responses/ShowRoom'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a room
      description: |
        Soft-deletes the room. Existing appointments are unaffected, but
        the room is removed from new-booking allocations.

        Requires the `SETTINGS_MANAGE` permission on the room's site.
      operationId: deleteRoom
      tags:
        - Rooms
      responses:
        '204':
          description: Room deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/rooms/{roomId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_roomId'
    post:
      summary: Duplicate a room
      description: |
        Creates a copy of an existing `Room`. The copy is created at the
        same site (or at `site_id` if you override it). Useful for seeding
        a second identically-configured room — e.g. "Treatment Room 2"
        off "Treatment Room 1".

        Requires the `SETTINGS_MANAGE` permission on the destination site.
      operationId: copyRoom
      tags:
        - Rooms
      requestBody:
        $ref: '#/components/requestBodies/CopyRoom'
      responses:
        '201':
          $ref: '#/components/responses/ShowRoom'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/reports/order-items:
    get:
      summary: List order items
      operationId: getOrderItemsReport
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a paginated list of individual order items, with optional filters and sorting.
        The response also includes a CSV variant when requesting with `Accept: text/csv`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-10'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/orderLabel'
        - $ref: '#/components/parameters/orderLabelIds'
        - $ref: '#/components/parameters/salesChannelId'
        - $ref: '#/components/parameters/salesChannelIds'
        - $ref: '#/components/parameters/parameters_offeringId'
        - $ref: '#/components/parameters/offeringIds'
        - $ref: '#/components/parameters/parameters_offeringType-2'
        - $ref: '#/components/parameters/offeringTypes'
        - $ref: '#/components/parameters/offeringCategory'
        - $ref: '#/components/parameters/offeringCategoryIds'
        - $ref: '#/components/parameters/parameters_status'
        - $ref: '#/components/parameters/statuses'
        - $ref: '#/components/parameters/orderStatus'
        - $ref: '#/components/parameters/orderStatuses'
        - $ref: '#/components/parameters/revenueDateFrom'
        - $ref: '#/components/parameters/revenueDateTo'
        - $ref: '#/components/parameters/parameters_dateFrom'
        - $ref: '#/components/parameters/parameters_dateTo'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtFrom'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtTo'
        - $ref: '#/components/parameters/itemDateFrom'
        - $ref: '#/components/parameters/itemDateTo'
        - $ref: '#/components/parameters/parameters_categoryId-3'
        - $ref: '#/components/parameters/categoryIds'
        - $ref: '#/components/parameters/brandIds'
        - $ref: '#/components/parameters/revenueCentres'
        - $ref: '#/components/parameters/soldById'
        - $ref: '#/components/parameters/soldByIds'
        - $ref: '#/components/parameters/parameters_practitionerId-3'
        - $ref: '#/components/parameters/practitionerIds'
        - $ref: '#/components/parameters/shopCategoryIds'
        - $ref: '#/components/parameters/parameters_roomId-2'
        - $ref: '#/components/parameters/roomIds'
        - $ref: '#/components/parameters/parameters_zoneId-2'
        - $ref: '#/components/parameters/zoneIds'
        - $ref: '#/components/parameters/parameters_sort-2'
        - $ref: '#/components/parameters/sortOrder'
      responses:
        '200':
          description: The data was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderItemsReportResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/order-items/queue:
    get:
      summary: Queue an export of the order items report
      tags:
        - Reports
      operationId: queueOrderItemsReport
      description: This endpoint queues an export of the order items report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-10'
        - $ref: '#/components/parameters/orderLabel'
        - $ref: '#/components/parameters/orderLabelIds'
        - $ref: '#/components/parameters/salesChannelId'
        - $ref: '#/components/parameters/salesChannelIds'
        - $ref: '#/components/parameters/parameters_offeringId'
        - $ref: '#/components/parameters/offeringIds'
        - $ref: '#/components/parameters/parameters_offeringType-2'
        - $ref: '#/components/parameters/offeringTypes'
        - $ref: '#/components/parameters/offeringCategory'
        - $ref: '#/components/parameters/offeringCategoryIds'
        - $ref: '#/components/parameters/parameters_status'
        - $ref: '#/components/parameters/statuses'
        - $ref: '#/components/parameters/orderStatus'
        - $ref: '#/components/parameters/orderStatuses'
        - $ref: '#/components/parameters/revenueDateFrom'
        - $ref: '#/components/parameters/revenueDateTo'
        - $ref: '#/components/parameters/parameters_dateFrom'
        - $ref: '#/components/parameters/parameters_dateTo'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtFrom'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtTo'
        - $ref: '#/components/parameters/itemDateFrom'
        - $ref: '#/components/parameters/itemDateTo'
        - $ref: '#/components/parameters/parameters_categoryId-3'
        - $ref: '#/components/parameters/categoryIds'
        - $ref: '#/components/parameters/brandIds'
        - $ref: '#/components/parameters/revenueCentres'
        - $ref: '#/components/parameters/soldById'
        - $ref: '#/components/parameters/soldByIds'
        - $ref: '#/components/parameters/parameters_practitionerId-3'
        - $ref: '#/components/parameters/practitionerIds'
        - $ref: '#/components/parameters/shopCategoryIds'
        - $ref: '#/components/parameters/parameters_roomId-2'
        - $ref: '#/components/parameters/roomIds'
        - $ref: '#/components/parameters/parameters_zoneId-2'
        - $ref: '#/components/parameters/zoneIds'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/order-revenues:
    get:
      summary: List order revenues
      operationId: getOrderRevenuesReport
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve one row per order, with gross, net and VAT revenue totals and a
        breakdown of final revenue by revenue centre. Only submitted and settled orders are included.
        The response also includes a CSV variant when requesting with `Accept: text/csv`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-11'
        - $ref: '#/components/parameters/parameters_revenueDateFrom'
        - $ref: '#/components/parameters/parameters_revenueDateTo'
      responses:
        '200':
          description: The order revenues were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderRevenuesReportResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/order-revenues/queue:
    get:
      summary: Queue an export of the order revenues report
      tags:
        - Reports
      operationId: queueOrderRevenuesReport
      description: This endpoint queues an export of the order revenues report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-11'
        - $ref: '#/components/parameters/parameters_revenueDateFrom'
        - $ref: '#/components/parameters/parameters_revenueDateTo'
      responses:
        '200':
          description: The request to queue the order revenues report was successful.
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/table-reservation-types:
    get:
      summary: List table reservation types
      operationId: listTableReservationTypes
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to retrieve a list of table reservation types for a site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListTableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Add a new table reservation type for the site.
      operationId: createTableReservationType
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to create a new table reservation type.
      requestBody:
        $ref: '#/components/requestBodies/CreateTableReservationTypeRequest'
      responses:
        '201':
          description: The table reservation type was created.
          $ref: '#/components/responses/TableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/table-reservation-types/{tableReservationTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_tableReservationTypeId'
    get:
      summary: Retrieve a single table reservation type
      operationId: getTableReservationType
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to retrieve a single table reservation type.
      responses:
        '200':
          $ref: '#/components/responses/TableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an existing table reservation type.
      operationId: updateTableReservationType
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to create a new table reservation type.
      requestBody:
        $ref: '#/components/requestBodies/UpdateTableReservationTypeRequest'
      responses:
        '200':
          description: The table reservation type was created.
          $ref: '#/components/responses/TableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a table reservation type
      operationId: deleteTableReservationType
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to soft delete a table reservation type.
      responses:
        '204':
          description: The table reservation type was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/table-reservation-types/{tableReservationTypeId}/options:
    parameters:
      - $ref: '#/components/parameters/parameters_tableReservationTypeId'
    post:
      summary: Add a new table reservation option.
      operationId: createTableReservationOption
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to add a new option to a table reservation type.
      requestBody:
        $ref: '#/components/requestBodies/CreateTableReservationOptionRequest'
      responses:
        '200':
          description: The option was created.
          $ref: '#/components/responses/TableReservationOptionResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/table-reservation-types/{tableReservationTypeId}/options/{optionId}:
    parameters:
      - $ref: '#/components/parameters/parameters_tableReservationTypeId'
      - $ref: '#/components/parameters/optionId'
    put:
      summary: Update an existing table reservation option.
      operationId: updateTableReservationOption
      tags:
        - TableReservationTypes
      description: |
        Use this endpoint to update a table reservation option.
      requestBody:
        $ref: '#/components/requestBodies/UpdateTableReservationOptionRequest'
      responses:
        '200':
          description: The integration config was created.
          $ref: '#/components/responses/TableReservationOptionResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove an option
      description: |
        Removes an option from a table reservation type
      operationId: deleteTableReservationOption
      tags:
        - TableReservationTypes
      responses:
        '204':
          description: The option was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/table-reservation-types/{tableReservationTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_tableReservationTypeId'
    post:
      summary: Restore a Table Reservation Type
      description: |
        This endpoint restores an archived (soft-deleted) Table Reservation Type by ID.
      tags:
        - TableReservationTypes
      operationId: restoreTableReservationType
      responses:
        '200':
          $ref: '#/components/responses/TableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/barcode-search/products/{code}:
    parameters:
      - $ref: '#/components/parameters/parameters_code'
      - $ref: '#/components/parameters/parameters_siteId-12'
    get:
      summary: Search products by barcode
      tags:
        - Products
      operationId: actionSearchProductsByBarcode
      description: |
        Use this endpoint to search for products by their barcode.
      responses:
        '200':
          description: A product was found
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          description: No product was found
          $ref: '#/components/responses/EntityNotFound'
  /shop/media:
    post:
      summary: Stores a media object
      description: Uploads some Media and returns a Media object.
      operationId: createMedia
      tags:
        - Media
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/CreateMedia'
      responses:
        '200':
          description: The media was successfully uploaded.
          content:
            application/json:
              schema:
                type: object
                title: CreateMediaResponse
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Media'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/media/{mediaId}:
    parameters:
      - $ref: '#/components/parameters/mediaId'
    get:
      summary: Retrieve a media object
      tags:
        - Media
      description: Retrieves details about the given Media object
      operationId: getMedia
      responses:
        '200':
          description: The media was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Media'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/ledger-line-postings:
    get:
      summary: List LedgerLinePostings
      operationId: listLedgerLinePostings
      tags:
        - LedgerLinePostings
      description: |
        Use this endpoint to retrieve a list of `LedgerLinePosting` resources associated with a `Site`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-13'
        - $ref: '#/components/parameters/parameters_status-2'
        - $ref: '#/components/parameters/parameters_sort-3'
        - $ref: '#/components/parameters/sortDirectionQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/createdAtFrom'
        - $ref: '#/components/parameters/createdAtTo'
        - $ref: '#/components/parameters/succeededAtFrom'
        - $ref: '#/components/parameters/succeededAtTo'
      responses:
        '200':
          description: The list of `LedgerLinePostings` resources was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListLedgerLinePostingsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/ledger-line-postings/{ledgerLinePostingId}:
    parameters:
      - $ref: '#/components/parameters/ledgerLinePostingId'
    get:
      summary: Show a LedgerLinePosting
      operationId: getLedgerLinePosting
      tags:
        - LedgerLinePostings
      description: |
        Use this endpoint to retrieve a `LedgerLinePosting`.
      responses:
        '200':
          description: The `LedgerLinePosting` was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ShowLedgerLinePostingResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a LedgerLinePosting
      operationId: updateLedgerLinePosting
      tags:
        - LedgerLinePostings
      description: |
        Use this endpoint to update the status of a `LedgerLinePosting`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateLedgerLinePosting'
      responses:
        '200':
          description: The `LedgerLinePosting` was successfully updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ShowLedgerLinePostingResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/ledger-line-postings/{ledgerLinePostingId}/retry:
    parameters:
      - $ref: '#/components/parameters/ledgerLinePostingId'
    post:
      summary: Retry a LedgerLinePosting
      tags:
        - LedgerLinePostings
      operationId: actionRetryLedgerLinePosting
      description: |
        Use this endpoint to retry a `LedgerLinePosting` that has failed.
      responses:
        '200':
          description: The request to retry a `LedgerLinePosting` was received
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ShowLedgerLinePostingResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/ledger-line-postings/{ledgerLinePostingId}/reverse:
    parameters:
      - $ref: '#/components/parameters/ledgerLinePostingId'
    post:
      summary: Reverse a LedgerLinePosting
      tags:
        - LedgerLinePostings
      operationId: actionReverseLedgerLinePosting
      description: |
        Use this endpoint to reverse a `LedgerLinePosting`. This action does not automatically attempt to post the new `LedgerLinePosting` to any integrations.
      responses:
        '200':
          description: The request to reverse a `LedgerLinePosting` was received
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ShowLedgerLinePostingResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/practitioner-rotas:
    get:
      summary: List all practitioner rotas
      description: |
        Returns a paginated list of every `PractitionerRota` the caller
        is authorised to see, across all practitioners. Useful for
        schedule management UIs that need to show a unified rota view.
        Use the nested `/shop/practitioners/{practitionerId}/rotas`
        endpoint when you already know the practitioner and want to
        avoid the extra filtering.
      tags:
        - PractitionerRotas
      operationId: listAllPractitionerRotas
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListAllPractitionerRotas'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a practitioner rota
      description: |
        Creates a new `PractitionerRota` for the practitioner identified
        by `practitioner_id` in the request body. Equivalent to calling
        the nested `POST /shop/practitioners/{practitionerId}/rotas`
        endpoint but doesn't require the practitioner ID in the URL.
      tags:
        - PractitionerRotas
      operationId: createPractitionerRotaStandalone
      requestBody:
        $ref: '#/components/requestBodies/CreatePractitionerRotaStandalone'
      responses:
        '201':
          $ref: '#/components/responses/ShowPractitionerRotaById'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioner-rotas/{practitionerRotaId}:
    parameters:
      - $ref: '#/components/parameters/practitionerRotaId'
    get:
      summary: Retrieve a practitioner rota by ID
      description: |
        Returns the `PractitionerRota` identified by `practitionerRotaId`.
        The rota record includes the `practitioner_id` it belongs to.
        Equivalent to calling the nested
        `GET /shop/practitioners/{practitionerId}/rotas/{rotaId}` endpoint
        but doesn't require the practitioner ID in the URL.
      tags:
        - PractitionerRotas
      operationId: getPractitionerRotaById
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerRotaById'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a practitioner rota by ID
      description: |
        Updates the `PractitionerRota` identified by `practitionerRotaId`.
        The practitioner the rota belongs to cannot be changed; create a
        new rota and delete the old one if you need to move the schedule
        between practitioners.
      tags:
        - PractitionerRotas
      operationId: updatePractitionerRotaById
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionerRotaStandalone'
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerRotaById'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a practitioner rota by ID
      description: |
        Deletes the `PractitionerRota` identified by `practitionerRotaId`.
        Any future availability windows generated from this rota are
        invalidated, but existing bookings are retained.
      tags:
        - PractitionerRotas
      operationId: deletePractitionerRotaById
      responses:
        '204':
          description: PractitionerRota deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/practitioner-tags:
    get:
      summary: List practitioner tags
      description: |
        Returns a paginated list of `PractitionerTag` objects within the
        caller's organisation. Use this to populate a tag picker when
        editing a practitioner, or to filter the calendar by tag.
      operationId: listPractitionerTags
      deprecated: true
      tags:
        - PractitionerTags
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPractitionerTags'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a practitioner tag
      description: |
        Creates a new `PractitionerTag` in the caller's organisation. The
        new tag has no practitioners attached until you assign it via the
        `Practitioner` update endpoint.
      operationId: createPractitionerTag
      deprecated: true
      tags:
        - PractitionerTags
      requestBody:
        $ref: '#/components/requestBodies/CreatePractitionerTag'
      responses:
        '201':
          $ref: '#/components/responses/ShowPractitionerTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioner-tags/{practitionerTagId}:
    parameters:
      - $ref: '#/components/parameters/practitionerTagId'
    get:
      summary: Retrieve a practitioner tag
      description: Returns a single `PractitionerTag` by ID.
      operationId: getPractitionerTag
      tags:
        - PractitionerTags
      deprecated: true
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a practitioner tag
      description: |
        Updates the `name` of an existing `PractitionerTag`. Tags cannot
        be moved between organisations.
      operationId: updatePractitionerTag
      deprecated: true
      tags:
        - PractitionerTags
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionerTag'
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a practitioner tag
      description: |
        Removes a `PractitionerTag`. Any practitioners that referenced
        the tag are automatically unlinked. This action is not reversible.
      operationId: deletePractitionerTag
      tags:
        - PractitionerTags
      deprecated: true
      responses:
        '204':
          description: Practitioner tag deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/practitioners:
    get:
      summary: Get all practitioners
      description: |
        Use this endpoint to retrieve all practitioners (paginated)
      tags:
        - Practitioners
      operationId: listAllPractitioners
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/parameters_query-6'
        - $ref: '#/components/parameters/parameters_zoneIds'
      responses:
        '200':
          $ref: '#/components/responses/ListPractitioners'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a practitioner
      description: |
        Creates a new `Practitioner` attached to one or more sites. The
        minimum body is `name` + `site_ids`; everything else has a sensible
        default or `null`-equivalent. Returns the freshly created
        practitioner.

        The first entry in `site_ids` becomes the practitioner's "default"
        site — zones, commission packages, and the user-uniqueness check
        are evaluated against this site. The practitioner's `timezone` is
        inherited from the default site at creation time.

        Requires the `SETTINGS_MANAGE` permission on every site listed in
        `site_ids`.
      tags:
        - Practitioners
      operationId: createPractitioner
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      requestBody:
        $ref: '#/components/requestBodies/CreatePractitioner'
      responses:
        '201':
          description: The practitioner was created.
          content:
            application/json:
              schema:
                title: CreatePractitionerResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Practitioner'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    get:
      summary: Retrieve a Practitioner
      description: Use this endpoint to retrieve a single `Practitioner` model.
      operationId: getPractitioner
      tags:
        - Practitioners
      responses:
        '200':
          description: Successfully retrieved the Practitioner
          content:
            application/json:
              schema:
                title: ShowPractitionerResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Practitioner'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a practitioner
      description: |
        Partially updates a `Practitioner`. Every field is optional; only
        fields you send are written. Fields you omit retain their current
        values. Requires the `SETTINGS_MANAGE` permission on the
        practitioner's first site.

        `email` (if sent) must be unique across all practitioners in the
        caller's organisations — duplicate emails are rejected with 422.
        `user_id` (if sent non-null) must share an organisation with the
        practitioner and not already be linked to another practitioner on
        the same site.
      operationId: updatePractitioner
      tags:
        - Practitioners
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitioner'
      responses:
        '200':
          description: The practitioner was updated.
          content:
            application/json:
              schema:
                title: UpdatePractitionerResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Practitioner'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a practitioner
      description: |
        Soft-deletes a `Practitioner`. Existing past appointments and
        sessions are unaffected; the practitioner is removed from new
        booking flows.

        **422 Unprocessable Entity** if the practitioner has future
        appointments or sessions still on the books — reassign or cancel
        those bookings first. The response lists `appointments` and/or
        `sessions` validation errors so callers know what to clear up.

        Requires the `SETTINGS_MANAGE` permission on the practitioner's
        first site.
      operationId: deletePractitioner
      tags:
        - Practitioners
      responses:
        '204':
          description: Practitioner deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    post:
      summary: Duplicate a practitioner
      description: |
        Creates a copy of an existing `Practitioner`. The copy inherits the
        source's full configuration (avatar, tags, zones, scheduling rules)
        except the underlying `user_id` association — the new practitioner
        starts without a linked user. Useful when staffing up similar roles
        or seeding a new site from a model practitioner.

        Requires the `SETTINGS_MANAGE` permission on the source's site.
      operationId: copyPractitioner
      tags:
        - Practitioners
      requestBody:
        $ref: '#/components/requestBodies/CopyPractitioner'
      responses:
        '201':
          description: The practitioner was copied.
          content:
            application/json:
              schema:
                title: CopyPractitionerResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Practitioner'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}/appointment-restrictions:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    get:
      summary: List appointment restrictions for a practitioner
      tags:
        - Practitioners
      operationId: listPractitionerAppointmentRestrictions
      description: |
        Returns the `PractitionerAppointmentRestriction`s configured on a
        practitioner. Restrictions either block the practitioner from
        certain appointment types or cap how long those appointments can
        be, optionally limited to a date range.

        The list is paginated. Requires the `RESERVATIONS_VIEW`
        permission on the practitioner's site.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPractitionerAppointmentRestrictions'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an appointment restriction for a practitioner
      tags:
        - Practitioners
      operationId: createPractitionerAppointmentRestriction
      description: |
        Adds a new `PractitionerAppointmentRestriction` to the
        practitioner. Use `type: cannot_offer` to stop the practitioner
        taking matching appointments outright, or `type: max_duration`
        with `max_duration` (minutes) to cap how long matching
        appointments can run.

        Requires the `SETTINGS_MANAGE` permission on the practitioner's
        site.
      requestBody:
        $ref: '#/components/requestBodies/CreatePractitionerAppointmentRestriction'
      responses:
        '201':
          $ref: '#/components/responses/ShowPractitionerAppointmentRestriction'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}/appointment-restrictions/{appointmentRestrictionId}:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
      - $ref: '#/components/parameters/appointmentRestrictionId'
    get:
      summary: Retrieve a practitioner appointment restriction
      tags:
        - Practitioners
      operationId: getPractitionerAppointmentRestriction
      description: |
        Returns a single `PractitionerAppointmentRestriction` belonging
        to the given practitioner. Requires the `RESERVATIONS_VIEW`
        permission on the practitioner's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerAppointmentRestriction'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a practitioner appointment restriction
      tags:
        - Practitioners
      operationId: updatePractitionerAppointmentRestriction
      description: |
        Replaces an existing `PractitionerAppointmentRestriction`. The
        server validates the same shape as on create, so `type` and
        `applies_to_type` are required and the conditional fields
        (`appointment_type_ids`, `category_ids`, `max_duration`) must be
        sent based on those values.

        Requires the `SETTINGS_MANAGE` permission on the practitioner's
        site.
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionerAppointmentRestriction'
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerAppointmentRestriction'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a practitioner appointment restriction
      tags:
        - Practitioners
      operationId: deletePractitionerAppointmentRestriction
      description: |
        Removes a `PractitionerAppointmentRestriction` from a
        practitioner. Future availability checks no longer apply the
        rule; existing bookings are unaffected.

        Requires the `SETTINGS_MANAGE` permission on the practitioner's
        site.
      responses:
        '204':
          description: Appointment restriction deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/practitioners/{practitionerId}/custom-availability:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    get:
      summary: List custom availability rules for a practitioner
      tags:
        - Practitioners
      operationId: listPractitionerCustomAvailability
      description: |
        Returns the `PractitionerCustomAvailability` rules for the
        practitioner. Each rule is an ad-hoc override to the regular
        rota — either opening an extra window (`is_available: true`) or
        blocking one off (`is_available: false`).

        Use the `date`, `date_time_from`, `date_time_to`, and
        `is_available` query parameters to narrow the result set.
        Results are paginated.
      parameters:
        - $ref: '#/components/parameters/parameters_date-3'
        - $ref: '#/components/parameters/parameters_dateTimeFrom'
        - $ref: '#/components/parameters/parameters_dateTimeTo'
        - $ref: '#/components/parameters/isAvailable'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPractitionerCustomAvailability'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a custom availability rule for a practitioner
      tags:
        - Practitioners
      operationId: createPractitionerCustomAvailability
      description: |
        Creates a new `PractitionerCustomAvailability` rule. Use this
        to open an extra working window (`is_available: true`) or to
        block one off (`is_available: false`, e.g. leave or sickness).

        The server validates that no confirmed appointments or sessions
        fall inside `is_available: false` windows, and automatically
        merges adjacent or overlapping rules with the same
        `is_available` value. The response is the resulting rule, which
        may have been merged with neighbours.
      requestBody:
        $ref: '#/components/requestBodies/CreatePractitionerCustomAvailability'
      responses:
        '201':
          $ref: '#/components/responses/ShowPractitionerCustomAvailability'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}/room-assignments:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    post:
      summary: Assign a room to a practitioner's custom availability on a date
      description: |
        Applies a room assignment (or clears one when `room_id` is null) to the
        practitioner's custom availability rules for the given `date` and time
        range. The server carves the matching availability segments and returns
        the resulting `PractitionerCustomAvailability` rules for that day.

        The request only succeeds when the target period falls within an
        existing availability window for the practitioner on that date.
      tags:
        - Practitioners
      operationId: actionAssignRoomToPractitionerCustomAvailability
      requestBody:
        $ref: '#/components/requestBodies/AssignRoomToPractitionerCustomAvailability'
      responses:
        '200':
          $ref: '#/components/responses/ListPractitionerCustomAvailability'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}/custom-availability/{customAvailabilityId}:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
      - $ref: '#/components/parameters/customAvailabilityId'
    get:
      summary: Retrieve a practitioner custom availability rule
      tags:
        - Practitioners
      operationId: getPractitionerCustomAvailability
      description: Returns a single `PractitionerCustomAvailability` rule belonging to the practitioner.
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerCustomAvailability'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a practitioner custom availability rule
      tags:
        - Practitioners
      operationId: updatePractitionerCustomAvailability
      description: |
        Updates a `PractitionerCustomAvailability` rule. Every body
        field is optional; sent fields replace the existing values.
        `date_time_to` must remain strictly after `date_time_from` once
        the update is applied.

        As on create, an update that overlaps or sits adjacent to
        another rule with the same `is_available` value triggers a
        merge. The response is the resulting rule.
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionerCustomAvailability'
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerCustomAvailability'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a practitioner custom availability rule
      tags:
        - Practitioners
      operationId: deletePractitionerCustomAvailability
      description: |
        Removes a `PractitionerCustomAvailability` rule. The
        practitioner's availability immediately reverts to the regular
        rota for the period the rule covered. Existing bookings are not
        affected.
      responses:
        '204':
          description: Custom availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/practitioners/{practitionerId}/rotas:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    get:
      summary: List rotas for a practitioner
      description: Returns a paginated list of `PractitionerRota` objects for the given practitioner.
      tags:
        - PractitionerRotas
      operationId: listPractitionerRotas
      parameters:
        - $ref: '#/components/parameters/parameters_practitionerId-4'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPractitionerRotasResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a rota for a practitioner
      description: Creates a new `PractitionerRota` for the given practitioner.
      tags:
        - PractitionerRotas
      operationId: createPractitionerRota
      requestBody:
        $ref: '#/components/requestBodies/CreatePractitionerRotaRequest'
      responses:
        '201':
          $ref: '#/components/responses/ShowPractitionerRotaResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/{practitionerId}/rotas/{rotaId}:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
      - $ref: '#/components/parameters/rotaId'
    get:
      summary: Retrieve a practitioner rota
      description: Use this endpoint to retrieve a single `PractitionerRota`.
      tags:
        - PractitionerRotas
      operationId: getPractitionerRota
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerRotaResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a practitioner rota
      description: Use this endpoint to update an existing `PractitionerRota`.
      tags:
        - PractitionerRotas
      operationId: updatePractitionerRota
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionerRotaRequest'
      responses:
        '200':
          $ref: '#/components/responses/ShowPractitionerRotaResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a practitioner rota
      description: Use this endpoint to delete a `PractitionerRota`.
      tags:
        - PractitionerRotas
      operationId: deletePractitionerRota
      responses:
        '204':
          description: PractitionerRota deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/room-tags:
    get:
      summary: List room tags
      description: |
        Returns a paginated list of `RoomTag` objects within the caller's
        organisation. Use this to populate a tag picker when editing a
        room, or to filter rooms in admin views.
      operationId: listRoomTags
      deprecated: true
      tags:
        - RoomTags
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListRoomTags'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a room tag
      description: |
        Creates a new `RoomTag` in the caller's organisation. The new tag
        has no rooms attached until you assign it via the `Room` update
        endpoint.
      operationId: createRoomTag
      deprecated: true
      tags:
        - RoomTags
      requestBody:
        $ref: '#/components/requestBodies/CreateRoomTag'
      responses:
        '201':
          $ref: '#/components/responses/ShowRoomTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/room-tags/{roomTagId}:
    parameters:
      - $ref: '#/components/parameters/roomTagId'
    get:
      summary: Retrieve a room tag
      description: Returns a single `RoomTag` by ID.
      operationId: getRoomTag
      deprecated: true
      tags:
        - RoomTags
      responses:
        '200':
          $ref: '#/components/responses/ShowRoomTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a room tag
      description: |
        Updates the `name` of an existing `RoomTag`. Tags cannot be moved
        between organisations.
      operationId: updateRoomTag
      deprecated: true
      tags:
        - RoomTags
      requestBody:
        $ref: '#/components/requestBodies/UpdateRoomTag'
      responses:
        '200':
          $ref: '#/components/responses/ShowRoomTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a room tag
      description: |
        Removes a `RoomTag`. Any rooms that referenced the tag are
        automatically unlinked. This action is not reversible.
      operationId: deleteRoomTag
      deprecated: true
      tags:
        - RoomTags
      responses:
        '204':
          description: Room tag deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/zones:
    get:
      summary: List zones
      description: |
        Returns a paginated list of `Zone` objects configured at the given
        site, ordered by name. Use this to populate a zone picker when
        configuring rooms, practitioners, or area-booking types.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listZones
      tags:
        - Zones
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListZones'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a zone
      description: |
        Creates a new `Zone` at a site. Requires the `SETTINGS_MANAGE`
        permission on the target site.
      operationId: createZone
      tags:
        - Zones
      requestBody:
        $ref: '#/components/requestBodies/CreateZone'
      responses:
        '201':
          $ref: '#/components/responses/ShowZone'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/zones/{zoneId}:
    parameters:
      - $ref: '#/components/parameters/parameters_zoneId-3'
    get:
      summary: Retrieve a zone
      description: |
        Returns a single `Zone` by ID. Requires the `RESERVATIONS_VIEW`
        permission on the zone's site.
      operationId: getZone
      tags:
        - Zones
      responses:
        '200':
          $ref: '#/components/responses/ShowZone'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a zone
      description: |
        Updates the `name` of an existing `Zone`. Requires the
        `SETTINGS_MANAGE` permission on the zone's site.
      operationId: updateZone
      tags:
        - Zones
      requestBody:
        $ref: '#/components/requestBodies/UpdateZone'
      responses:
        '200':
          $ref: '#/components/responses/ShowZone'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a zone
      description: |
        Removes a `Zone`. Resources that referenced the zone retain the
        (now-invalid) ID until their next update — the booking engine
        treats missing zones as unrestricted. Requires the
        `SETTINGS_MANAGE` permission on the zone's site.
      operationId: deleteZone
      tags:
        - Zones
      responses:
        '204':
          description: Zone deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/tax-configurations:
    get:
      summary: Get revenue centres for a site
      tags:
        - TaxConfigurations
      operationId: getTaxConfigurations
      parameters:
        - $ref: '#/components/parameters/country_code'
      description: |
        Use this endpoint to retrieve tax configurations.
      responses:
        '200':
          $ref: '#/components/responses/ListTaxConfigurations'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/tax-configurations/{taxConfigurationId}:
    parameters:
      - $ref: '#/components/parameters/taxConfigurationId'
    get:
      summary: Retrieve a tax configuration
      tags:
        - TaxConfigurations
      operationId: getTaxConfiguration
      description: |
        Retrieve a single tax configuration by ID. The response includes the
        configuration's name, optional description, and the full set of rate
        sets that apply to it — useful for surfacing the active tax rules in
        a back-office editor, or for previewing what rates will be applied
        before testing a calculation against `/calculate`.
      responses:
        '200':
          $ref: '#/components/responses/ShowTaxConfiguration'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/tax-configurations/{taxConfigurationId}/calculate:
    parameters:
      - $ref: '#/components/parameters/taxConfigurationId'
    post:
      summary: Test a tax calculation.
      tags:
        - TaxConfigurations
      operationId: actionTestTaxConfiguration
      description: |
        Use this endpoint to test a tax calculation for the given tax configuration.
      requestBody:
        $ref: '#/components/requestBodies/TestTaxConfiguration'
      responses:
        '200':
          $ref: '#/components/responses/TestTaxConfiguration'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/visit-intake-forms-for-orders/queue-pdf:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-14'
      - $ref: '#/components/parameters/basketIds'
    get:
      summary: Export intake forms queue
      description: |
        This endpoint queues an export of intake forms for the given basket IDs.
      operationId: actionQueueIntakeFormsExport
      tags:
        - Reports
      responses:
        '200':
          description: The request to queue the export of the `Intake Forms` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/visits/{visitId}:
    parameters:
      - $ref: '#/components/parameters/visitId'
  /shop/visits/{visitId}/send:
    parameters:
      - $ref: '#/components/parameters/visitId'
  /shop/visits/{visitId}/guests:
    parameters:
      - $ref: '#/components/parameters/visitId'
  /shop/visits/{visitId}/guests/{guestId}:
    parameters:
      - $ref: '#/components/parameters/visitId'
      - $ref: '#/components/parameters/guestId'
  /shop/visits/{visitId}/guests/{guestId}/complete-check-in:
    parameters:
      - $ref: '#/components/parameters/visitId'
      - $ref: '#/components/parameters/guestId'
    post:
      summary: Complete a visit guest's check-in
      description: |
        Marks the guest identified by `guestId` as checked in for their
        parent `Visit`. The action is idempotent — calling it again on a
        guest that is already checked in is a no-op and returns the same
        `204 No Content`. No request body.

        Use this when a guest physically arrives at the venue: it
        finalises the check-in started at the kiosk or front desk, marks
        any open intake-form sessions as complete for the guest, and
        propagates the check-in status to downstream integrations.

        Requires the `RESERVATIONS_MANAGE` permission on the visit's site.
      operationId: actionCompleteVisitGuestCheckIn
      tags:
        - Visits
      responses:
        '204':
          description: The guest was successfully checked in.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/visits/{customerId}/customer:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
  /shop/visit-types:
    get:
      summary: Show VisitTypes
      description: |
        This endpoint retrieves a list of `VisitType`s.
      tags:
        - VisitType
      operationId: listVisitTypes
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-15'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListVisitTypesResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create VisitType
      description: |
        This endpoint creates a new `VisitType`.
      tags:
        - VisitType
      operationId: createVisitType
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-15'
      requestBody:
        $ref: '#/components/requestBodies/CreateVisitTypeRequest'
      responses:
        '201':
          $ref: '#/components/responses/ShowVisitTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/visit-types/{visitTypeId}:
    parameters:
      - $ref: '#/components/parameters/visitTypeId'
    get:
      summary: Show a VisitType
      description: |
        Use this endpoint to retrieve a `VisitType`
      tags:
        - VisitType
      operationId: getVisitType
      responses:
        '200':
          $ref: '#/components/responses/ShowVisitTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a VisitType
      description: |
        Use this endpoint to update an existing `VisitType`.
      tags:
        - VisitType
      operationId: updateVisitType
      requestBody:
        $ref: '#/components/requestBodies/UpdateVisitTypeRequest'
      responses:
        '201':
          $ref: '#/components/responses/ShowVisitTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a VisitType
      description: |
        Use this endpoint to archive a `VisitType`.
      tags:
        - VisitType
      operationId: deleteVisitType
      responses:
        '204':
          description: VisitType archived
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/visit-types/{visitTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/visitTypeId'
    post:
      summary: Restore a VisitType
      description: |
        Use this endpoint to restore an archived `VisitType`.
      tags:
        - VisitType
      operationId: restoreVisitType
      responses:
        '200':
          $ref: '#/components/responses/ShowVisitTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/webhook-configs/{webhookConfigId}:
    parameters:
      - $ref: '#/components/parameters/webhookConfigId'
  /shop/webhook-configs/{webhookConfigId}/restore:
    parameters:
      - $ref: '#/components/parameters/webhookConfigId'
  /shop/voucher-types:
    get:
      summary: List Voucher Types
      tags:
        - VoucherTypes
      operationId: listVoucherTypes
      description: |
        This endpoint lists all the `VoucherTypes` which are associated with the given site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/amountType'
        - $ref: '#/components/parameters/customisableAmount'
        - $ref: '#/components/parameters/parameters_query-7'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListVoucherTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a voucher type
      description: |
        Creates a new `VoucherType` on the site identified by the `site_id`
        query parameter, attributed to the caller's primary organisation.
        `name` is required; everything else has a sensible default.

        The body's shape depends on `amount_type`:

        - `amount_type=cash` uses `amount`, `customisable_amount`, and
          `partially_redeemable`; the discount-to-zero-only fields are
          forced to `null` server-side.
        - `amount_type=discount_to_zero` uses `valid_weekdays`,
          `invalid_date_set_ids`, `valid_offerings`, and `invalid_offerings`;
          the cash-only fields are ignored.

        The new voucher type's `min_price` / `max_price` are seeded from the
        submitted price at create time. Requires `SETTINGS_MANAGE` on the
        target site.
      operationId: createVoucherType
      tags:
        - VoucherTypes
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      requestBody:
        $ref: '#/components/requestBodies/CreateVoucherType'
      responses:
        '201':
          $ref: '#/components/responses/ShowVoucherType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-types/{voucherTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherTypeId'
    get:
      summary: Retrieve a VoucherType
      description: Use this endpoint to retrieve a `VoucherType` model.
      operationId: getVoucherType
      tags:
        - VoucherTypes
      responses:
        '200':
          description: The VoucherType was successfully retrieved
          content:
            application/json:
              schema:
                title: ShowVoucherType
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/VoucherType'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a voucher type
      description: |
        Updates an existing `VoucherType`. `name` is required (the validator
        re-asserts it on every update); other fields are optional and
        omitted fields retain their current values. Cash- vs
        discount-to-zero-specific fields are conditionally enforced — see
        the request body for details.

        Sending `category_ids: []` explicitly clears the category list (the
        only way to wipe categories — omitting the key leaves them
        unchanged).

        Requires the `SETTINGS_MANAGE` permission on the voucher type's
        site.
      operationId: updateVoucherType
      tags:
        - VoucherTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateVoucherType'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a voucher type
      description: |
        Soft-deletes the voucher type. Existing vouchers already sold under
        this type remain valid and redeemable; the type itself is removed
        from new-sale flows. Use `POST .../restore` to bring it back.

        Requires the `SETTINGS_MANAGE` permission on the voucher type's
        site. No request body.
      operationId: deleteVoucherType
      tags:
        - VoucherTypes
      responses:
        '204':
          description: Voucher type deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/voucher-types/{voucherTypeId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherTypeId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a VoucherType
      description: Returns the localised `name` and `description` for the given locale.
      operationId: getVoucherTypeLocaleStrings
      tags:
        - VoucherTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a VoucherType
      description: Sets the localised `name` and/or `description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateVoucherTypeLocaleStrings
      tags:
        - VoucherTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateVoucherTypeLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateVoucherTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-types/{voucherTypeId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherTypeId'
    get:
      summary: List availability rules for a voucher type
      tags:
        - VoucherTypes
      operationId: listVoucherTypeAvailabilityRules
      description: |
        Returns all `AvailabilityRule`s configured on a `VoucherType`.
        Availability rules carve up the calendar into windows when
        vouchers of this type can or cannot be redeemed — useful for
        blocking peak holiday dates, restricting redemptions to specific
        seasons, or only allowing redemption from a future opening date.

        Rule semantics: any `is_available: false` rule overrides any
        `is_available: true` rule for the same period.
      responses:
        '200':
          $ref: '#/components/responses/ListVoucherTypeAvailabilityRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an availability rule for a voucher type
      tags:
        - VoucherTypes
      operationId: createVoucherTypeAvailabilityRule
      description: |
        Adds a new `AvailabilityRule` to a `VoucherType`. Use
        `is_available: true` to open redemption windows, or
        `is_available: false` to block redemptions during the supplied
        date range. Omit the dates to apply the rule from today
        onwards with no end date.

        Requires the `update` ability on the voucher type.
      requestBody:
        $ref: '#/components/requestBodies/CreateVoucherTypeAvailabilityRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowVoucherTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-types/{voucherTypeId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherTypeId'
      - $ref: '#/components/parameters/availabilityRuleId'
    get:
      summary: Retrieve a voucher type availability rule
      tags:
        - VoucherTypes
      operationId: getVoucherTypeAvailabilityRule
      description: Returns a single `AvailabilityRule` belonging to the given `VoucherType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a voucher type availability rule
      tags:
        - VoucherTypes
      operationId: updateVoucherTypeAvailabilityRule
      description: |
        Replaces an `AvailabilityRule` on a `VoucherType`. The server
        validates the same shape as on create, so `is_available` is
        required and any supplied dates must keep `date_to` on or after
        `date_from`. Requires the `update` ability on the voucher type.
      requestBody:
        $ref: '#/components/requestBodies/UpdateVoucherTypeAvailabilityRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherTypeAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a voucher type availability rule
      tags:
        - VoucherTypes
      operationId: deleteVoucherTypeAvailabilityRule
      description: |
        Removes an `AvailabilityRule` from a `VoucherType`. Redemption
        windows are recomputed from the remaining rules. Vouchers
        already issued are not affected.
      responses:
        '204':
          description: Availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/voucher-types/{voucherTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherTypeId'
    post:
      summary: Duplicate a voucher type
      description: |
        Creates a copy of an existing `VoucherType` with the supplied fields
        overlaid on top. Useful when seeding a near-identical offering off
        an existing one. The new voucher type is created under the same
        site and organisation as the original; you can override any
        write-able field by sending it in the body. Fields omitted from the
        body are inherited from the source verbatim.

        `name` is required so the new copy is distinguishable from the
        source. The `amount_type`-based field rules apply just as on create
        — see the request body for details.

        Requires the `SETTINGS_MANAGE` permission on the original voucher
        type's site.
      operationId: copyVoucherType
      tags:
        - VoucherTypes
      requestBody:
        $ref: '#/components/requestBodies/CopyVoucherType'
      responses:
        '201':
          $ref: '#/components/responses/ShowVoucherType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-types/{voucherTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherTypeId'
    post:
      summary: Restore a deleted voucher type
      description: |
        Un-deletes a previously soft-deleted `VoucherType`. The voucher
        type returns to its pre-deletion state, including price, validity
        rules, valid/invalid offerings, and delivery options. Existing
        vouchers already sold under this type remain unaffected.

        Requires the `SETTINGS_MANAGE` permission on the voucher type's
        site. No request body.
      operationId: restoreVoucherType
      tags:
        - VoucherTypes
      responses:
        '200':
          description: The voucher type was restored successfully.
          content:
            application/json:
              schema:
                title: RestoreVoucherTypeResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VoucherType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/voucher-delivery-options/{voucherDeliveryOptionId}:
    parameters:
      - $ref: '#/components/parameters/voucherDeliveryOptionId'
  /shop/voucher-delivery-options/{voucherDeliveryOptionId}/restore:
    parameters:
      - $ref: '#/components/parameters/voucherDeliveryOptionId'
  /shop/vouchers:
    get:
      summary: List Vouchers
      description: |
        Returns a paginated list of `Voucher`s imported into the site. The
        list reflects vouchers managed by an external processor (e.g.
        GiftPro) that have been synced into Trybe via a previous
        `importVouchers` run.

        Requires the `RESERVATIONS_VIEW` permission on the target site.
      operationId: listVouchers
      tags:
        - Vouchers
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListVouchers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/vouchers/import:
    get:
      summary: Import vouchers from the site's voucher processor
      description: |
        Kicks off an asynchronous import that pulls the latest catalogue of
        vouchers from the site's configured voucher processor (e.g.
        GiftPro) and reconciles them with Trybe's local `Voucher` records.
        Vouchers present in the source system but missing in Trybe are
        created; existing records are updated to reflect any changes to
        name, price, currency, or redemption rules.

        The endpoint returns a `QueuedJob` immediately — poll the queued
        job's status to track completion. The import does not block the
        request, so newly synced vouchers may not appear in `listVouchers`
        for a few seconds after the job completes.

        Requires the `SETTINGS_MANAGE` permission on the target site.
      operationId: queueImportVouchers
      tags:
        - Vouchers
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/vouchers/codes/{code}:
    parameters:
      - $ref: '#/components/parameters/parameters_code-2'
    get:
      summary: Look up a voucher by its redemption code
      description: |
        Resolves a redemption code to a usable voucher and reports its
        current redeemable balance, expiry window, and the offerings it
        may be applied to. Use this endpoint at the point of sale to
        validate a code presented by a customer before applying it as
        payment.

        The lookup follows a two-tier search:

        1. Trybe-native `VoucherCode`s issued through the basket are checked
           first; if found, the voucher's usability is asserted (it must be
           within its validity window and have balance remaining) and the
           canonical record is returned.
        2. If the site has an active voucher integration (e.g. GiftPro),
           the code is then looked up in the external processor. External
           vouchers are returned in the same response shape with
           `payment_processor=external_voucher`.

        Returns `400 Bad Request` if the code is found but is already
        fully redeemed or expired, and `404 Not Found` if the code does
        not exist in either store.
      operationId: actionCheckVoucherCode
      tags:
        - Vouchers
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherCodeLookup'
        '400':
          description: |
            The voucher code is recognised but cannot be redeemed —
            typically because it has already been redeemed or has expired.
          content:
            application/json:
              schema:
                title: CheckVoucherCodeBadRequestResponse
                type: object
                additionalProperties: false
                properties:
                  message:
                    type: string
                    description: Human-readable reason the voucher cannot be redeemed.
                    example: This voucher has already been redeemed.
                required:
                  - message
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/vouchers/{voucherId}:
    parameters:
      - $ref: '#/components/parameters/voucherId'
    get:
      summary: Retrieve a Voucher
      description: |
        Returns a single imported `Voucher`, enriched with the display
        names of every offering in its `valid_offerings` allowlist.

        Requires the `view` ability on the `Voucher` — granted by holding
        `RESERVATIONS_VIEW` on the voucher's site.
      operationId: getVoucher
      tags:
        - Vouchers
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucher'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Voucher
      description: |
        Updates the redemption rules attached to an imported `Voucher`.
        Currently three fields are mutable — `valid_offerings`,
        `valid_weekdays`, and `invalid_date_set_ids`. Other catalogue
        fields (name, price, currency, processor metadata) are sourced
        from the upstream processor and refresh on the next
        `importVouchers` run.

        Requires the `update` ability on the `Voucher` — typically granted
        by holding `SETTINGS_MANAGE` on the voucher's site.
      operationId: updateVoucher
      tags:
        - Vouchers
      requestBody:
        $ref: '#/components/requestBodies/UpdateVoucher'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucher'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/vouchers/{voucherId}/offerings:
    parameters:
      - $ref: '#/components/parameters/voucherId'
    post:
      summary: Add an offering to a voucher's valid-offerings allowlist
      description: |
        Appends a single offering to the voucher's `valid_offerings` list.
        No-op if the offering is already present (idempotent on
        `offering_id`).

        Use the bulk `updateVoucher` endpoint when replacing the entire
        allowlist in one call.

        Requires the `update` ability on the `Voucher` — typically granted
        by holding `SETTINGS_MANAGE` on the voucher's site.
      operationId: createVoucherValidOffering
      tags:
        - Vouchers
      requestBody:
        $ref: '#/components/requestBodies/CreateVoucherValidOffering'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucher'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/vouchers/{voucherId}/offerings/{offeringId}:
    parameters:
      - $ref: '#/components/parameters/voucherId'
      - $ref: '#/components/parameters/parameters_offeringId-2'
    delete:
      summary: Remove an offering from a voucher's valid-offerings allowlist
      description: |
        Removes the offering identified by `offeringId` from the voucher's
        `valid_offerings` list. No-op if the offering is not present.
        Returns the updated `Voucher` with offering display names included.

        Requires the `update` ability on the `Voucher` — typically granted
        by holding `SETTINGS_MANAGE` on the voucher's site.
      operationId: deleteVoucherValidOffering
      tags:
        - Vouchers
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucher'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers:
    get:
      summary: List Customers
      tags:
        - Customers
      operationId: listCustomers
      description: |
        This endpoint lists the `Customer`s which are associated to the provided site.
      parameters:
        - $ref: '#/components/parameters/parameters_query-8'
        - $ref: '#/components/parameters/parameters_email'
        - $ref: '#/components/parameters/organisation_id'
        - $ref: '#/components/parameters/brand_id'
        - $ref: '#/components/parameters/site_id'
        - $ref: '#/components/parameters/membership_number'
        - $ref: '#/components/parameters/name'
        - $ref: '#/components/parameters/phone'
        - $ref: '#/components/parameters/membership'
        - $ref: '#/components/parameters/membership_created_at_from'
        - $ref: '#/components/parameters/membership_created_at_to'
        - $ref: '#/components/parameters/membership_type_id'
        - $ref: '#/components/parameters/membership_rate_id'
        - $ref: '#/components/parameters/marketing_opt_in'
        - $ref: '#/components/parameters/label_ids'
        - $ref: '#/components/parameters/created_at_from'
        - $ref: '#/components/parameters/created_at_to'
        - $ref: '#/components/parameters/id'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a Customer
      description: |
        Use this endpoint to create a new `Customer`.

        When creating a new `Customer`, you must specify at least one of the following fields along with any other fields marked as required:

        - `email`
        - `first_name`
        - `last_name`
      tags:
        - Customers
      operationId: createCustomer
      requestBody:
        $ref: '#/components/requestBodies/CreateCustomer'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomer'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: Show a Customer
      description: |
        Use this endpoint to retrieve a `Customer` by their ID.
      tags:
        - Customers
      operationId: getCustomer
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Customer
      description: |
        Use this endpoint to update an existing `Customer`.
      tags:
        - Customers
      operationId: updateCustomer
      requestBody:
        $ref: '#/components/requestBodies/UpdateCustomer'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomer'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      deprecated: true
      summary: Delete a Customer
      description: |
        Anonymises the given `Customer`. The customer record is retained for
        accounting and reporting purposes but personally identifiable
        information is scrubbed.
      tags:
        - Customers
      operationId: deleteCustomer_deprecated
      responses:
        '204':
          description: The customer was successfully anonymised
        '400':
          description: The customer could not be anonymised
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/{customerId}/barcodes:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List Associated Barcodes for a Customer
      description: |
        This endpoint retrieves all barcodes associated with a customer.
      tags:
        - Customers
      operationId: listAssociatedBarcodes
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListAssociatedBarcodes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/{customerId}/barcodes/{barcodeId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/barcodeId'
    delete:
      summary: Delete an associated barcode for a customer
      tags:
        - Customers
      operationId: deleteAssociatedBarcode
      description: |
        This endpoint deletes an associated barcode for a customer.
      responses:
        '204':
          description: The associated barcode was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The customer or associated barcode could not be found
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an associated barcode for a customer
      tags:
        - Customers
      operationId: updateAssociatedBarcode
      description: |
        This endpoint updates the details of an associated barcode for a customer.
      requestBody:
        $ref: '#/components/requestBodies/UpdateAssociatedBarcode'
      responses:
        '200':
          description: The associated barcode was successfully updated
          $ref: '#/components/responses/ShowAssociatedBarcode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The customer or associated barcode could not be found
          $ref: '#/components/responses/EntityNotFound'
        '422':
          description: The request to update the associated barcode was invalid
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/memberships:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List a customer's memberships
      description: |
        Use this endpoint to retrieve a list of `Membership`s for the given `Customer`.

        When retrieving memberships with this endpoint, the `next_charge` property will be populated if applicable.
      tags:
        - Customers
      operationId: getCustomerMemberships
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerMemberships'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/lock:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    post:
      summary: Lock a Customer
      description: |
        Use this endpoint to lock a `Customer`.

        When a customer is locked, their details cannot be modified until their profile is unlocked.

        Any requests to [`updateCustomer`](/endpoints/Customers/#updateCustomer) or [`anonymiseCustomer`](/endpoints/Customers/#anonymiseCustomer) will fail with a `400` response.
      tags:
        - Customers
      operationId: actionLockCustomer
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/unlock:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    post:
      summary: Unlock a Customer
      description: |
        Use this endpoint to unlock a `Customer`.
      tags:
        - Customers
      operationId: actionUnlockCustomer
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/reset-password:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    post:
      summary: Trigger reset password
      description: |
        Use this endpoint to trigger a password reset for a `Customer`.

        The customer will receive a URL via email which they can use to reset their password.

        The URL will be valid for 1 hour.
      tags:
        - Customers
      operationId: actionTriggerCustomerPasswordReset
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/resend-verification:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    post:
      summary: Resend verification
      description: |
        Use this endpoint to resend the email verification email for a `Customer`.

        The customer will receive a URL via email which they can use to verify their email address.
      tags:
        - Customers
      operationId: actionResendCustomerVerification
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/marketing-preferences:
    get:
      summary: List marketing preferences
      tags:
        - MarketingPreferences
      operationId: listMarketingPreferences
      description: |
        This endpoint retrieves all the marketing preferences associated with an organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId'
      responses:
        '200':
          $ref: '#/components/responses/ListMarketingPreferences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a marketing preference
      tags:
        - MarketingPreferences
      operationId: createMarketingPreference
      description: |
        This endpoint creates a new marketing preference for an organisation.
      requestBody:
        $ref: '#/components/requestBodies/CreateMarketingPreference'
      responses:
        '201':
          $ref: '#/components/responses/ShowMarketingPreference'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/marketing-preferences/{marketingPreferenceId}:
    parameters:
      - $ref: '#/components/parameters/marketingPreferenceId'
    get:
      summary: Get a single marketing preference for an organisation
      tags:
        - MarketingPreferences
      operationId: getMarketingPreference
      description: |
        This endpoint retrieves a single marketing preference belonging to an organisation.
      responses:
        '200':
          $ref: '#/components/responses/ShowMarketingPreference'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a marketing preference for an organisation
      tags:
        - MarketingPreferences
      operationId: updateMarketingPreference
      description: |
        This endpoint updates a marketing preference belonging to an organisation.
      requestBody:
        $ref: '#/components/requestBodies/UpdateMarketingPreference'
      responses:
        '200':
          $ref: '#/components/responses/ShowMarketingPreference'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a marketing preference for an organisation
      tags:
        - MarketingPreferences
      operationId: deleteMarketingPreference
      description: |
        This endpoint deletes a marketing preference belonging to an organisation.
      responses:
        '204':
          description: The marketing preference was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/payment-methods:
    get:
      summary: List Payment Methods
      tags:
        - PaymentMethods
      operationId: listPaymentMethods
      description: |
        This endpoint retrieves a list of all payment methods.
      parameters:
        - $ref: '#/components/parameters/customer_id'
        - $ref: '#/components/parameters/parameters_type'
        - $ref: '#/components/parameters/processor'
        - $ref: '#/components/parameters/parameters_status-3'
        - $ref: '#/components/parameters/membership_payment_method'
        - $ref: '#/components/parameters/for_barcode'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPaymentMethods'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/sites/{siteId}/gantner/usage-notifications:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
  /customers/sites/{siteId}/gantner/configuration-file:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
  /customers/sites/{siteId}/gantner/devices:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
  /customers/sites/{siteId}/gantner/devices/{deviceId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/deviceId'
  /customers/sites/{siteId}/gantner/devices/{deviceId}/open:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/deviceId'
  /customers/sites/{siteId}/marketing-preferences:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
    get:
      summary: List the marketing preferences for a site
      tags:
        - MarketingPreferences
      operationId: listSiteMarketingPreferences
      description: |
        This endpoint retrieves all the marketing preferences associated with a site.
      responses:
        '200':
          $ref: '#/components/responses/ListSiteMarketingPreferences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Enable a marketing preference for a site
      tags:
        - MarketingPreferences
      operationId: createSiteMarketingPreference
      description: |
        This endpoint enables a marketing preference for a site.
      requestBody:
        $ref: '#/components/requestBodies/CreateSiteMarketingPreference'
      responses:
        '201':
          $ref: '#/components/responses/ShowMarketingPreference'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/sites/{siteId}/marketing-preferences/{marketingPreferenceId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/marketingPreferenceId'
    delete:
      summary: Disable a marketing preference for a site
      tags:
        - MarketingPreferences
      operationId: deleteSiteMarketingPreference
      description: |
        This endpoint disables a marketing preference for a site.
      responses:
        '204':
          description: The marketing preference was successfully disabled
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/sites/{siteId}/membership-types:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
    get:
      summary: List the membership types for a site
      tags:
        - MembershipTypes
      operationId: listSiteMembershipTypes
      description: |
        This endpoint retrieves all the membership types associated with a site.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSiteMembershipTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Enable a membership type for a site
      tags:
        - MembershipTypes
      operationId: createSiteMembershipType
      description: |
        This endpoint enables a membership type for a site.
      requestBody:
        $ref: '#/components/requestBodies/CreateSiteMembershipType'
      responses:
        '201':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/sites/{siteId}/membership-types/{membershipTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/parameters_membershipTypeId'
    delete:
      summary: Disable a membership type for a site
      tags:
        - MembershipTypes
      operationId: deleteSiteMembershipType
      description: |
        This endpoint disables a membership type for a site.
      responses:
        '204':
          description: The membership type was successfully disabled
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    get:
      summary: Check whether a membership type is enabled for a site
      tags:
        - MembershipTypes
      operationId: listSingleSiteMembershipType
      description: |
        This endpoint checks for the existence of a site membership type for a given membership type.
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/brands:
    get:
      summary: List Inventory Brands
      tags:
        - InventoryBrands
      operationId: listInventoryBrands
      description: |
        This endpoint retrieves a list of all the inventory brands for the given organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-17'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/parameters_query-9'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryBrands'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create an Inventory Brand
      tags:
        - InventoryBrands
      operationId: createInventoryBrand
      description: |
        This endpoint creates an inventory brand for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryBrand'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryBrand'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/brands/{brandId}:
    parameters:
      - $ref: '#/components/parameters/brandId'
    get:
      summary: Show an Inventory Brand
      tags:
        - InventoryBrands
      operationId: getInventoryBrand
      description: |
        This endpoint retrieves an inventory brand for the given organisation.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryBrand'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Inventory Brand
      tags:
        - InventoryBrands
      operationId: updateInventoryBrand
      description: |
        This endpoint updates an inventory brand for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryBrand'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryBrand'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive an Inventory Brand
      tags:
        - InventoryBrands
      operationId: deleteInventoryBrand
      description: |
        This endpoint soft deletes an inventory brand for the given organisation.
      responses:
        '204':
          description: The inventory brand was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/brands/{brandId}/restore:
    parameters:
      - $ref: '#/components/parameters/brandId'
    post:
      summary: Restore an Inventory Brand
      description: |
        This endpoint restores an archived (soft-deleted) inventory brand by ID.
      tags:
        - InventoryBrands
      operationId: restoreInventoryBrand
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryBrand'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/categories:
    get:
      summary: List Inventory Categories
      tags:
        - InventoryCategories
      operationId: listInventoryCategories
      description: |
        This endpoint retrieves a list of all the inventory categories for the given organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-18'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/parameters_query-10'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryCategories'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create an Inventory Category
      tags:
        - InventoryCategories
      operationId: createInventoryCategory
      description: |
        This endpoint creates an inventory category for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryCategory'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/categories/order:
    put:
      summary: Reorder Inventory Categories
      tags:
        - InventoryCategories
      operationId: updateInventoryCategoriesOrder
      description: |
        This endpoint persists the display order of inventory categories for a
        given site. The position of each ID in the `category_ids` array is stored
        as that category's order. All IDs must belong to the caller's site and
        organisation and must not be archived.
      requestBody:
        $ref: '#/components/requestBodies/ReorderInventoryCategories'
      responses:
        '204':
          description: The inventory categories were successfully reordered.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/categories/{categoryId}:
    parameters:
      - $ref: '#/components/parameters/parameters_categoryId-4'
    get:
      summary: Show an Inventory Category
      tags:
        - InventoryCategories
      operationId: getInventoryCategory
      description: |
        This endpoint retrieves an inventory category for the given organisation.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Inventory Category
      tags:
        - InventoryCategories
      operationId: updateInventoryCategory
      description: |
        This endpoint updates an inventory category for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryCategory'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive an Inventory Category
      tags:
        - InventoryCategories
      operationId: deleteInventoryCategory
      description: |
        This endpoint soft deletes an inventory category for the given organisation.
      responses:
        '204':
          description: The inventory category was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/categories/{categoryId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_categoryId-4'
    post:
      summary: Restore an Inventory Category
      description: |
        This endpoint restores an archived (soft-deleted) inventory category by ID.
      tags:
        - InventoryCategories
      operationId: restoreInventoryCategory
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/suppliers:
    get:
      summary: List Suppliers
      tags:
        - Suppliers
      operationId: listSuppliers
      description: |
        This endpoint retrieves a list of all the suppliers for the given organisation.
      parameters:
        - $ref: '#/components/parameters/ids'
        - $ref: '#/components/parameters/parameters_siteId-19'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/parameters_query-11'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSuppliers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a Supplier
      tags:
        - Suppliers
      operationId: createSupplier
      description: |
        This endpoint creates a supplier for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/CreateSupplier'
      responses:
        '201':
          $ref: '#/components/responses/ShowSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/suppliers/{supplierId}:
    parameters:
      - $ref: '#/components/parameters/supplierId'
    get:
      summary: Show a Supplier
      tags:
        - Suppliers
      operationId: getSupplier
      description: |
        This endpoint retrieves a single supplier for the given organisation.
      responses:
        '200':
          $ref: '#/components/responses/ShowSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Supplier
      tags:
        - Suppliers
      operationId: updateSupplier
      description: |
        This endpoint updates a single supplier for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/UpdateSupplier'
      responses:
        '200':
          $ref: '#/components/responses/ShowSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a Supplier
      tags:
        - Suppliers
      operationId: deleteSupplier
      description: |
        This endpoint soft deletes a single supplier for the given organisation.
      responses:
        '204':
          description: The supplier was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/suppliers/{supplierId}/copy:
    parameters:
      - $ref: '#/components/parameters/supplierId'
    post:
      summary: Copy a Supplier
      description: |
        This endpoint copies an existing supplier by ID.
      tags:
        - Suppliers
      operationId: actionSupplier
      requestBody:
        $ref: '#/components/requestBodies/CopySupplier'
      responses:
        '200':
          $ref: '#/components/responses/ShowSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/suppliers/{supplierId}/restore:
    parameters:
      - $ref: '#/components/parameters/supplierId'
    post:
      summary: Restore a Supplier
      description: |
        This endpoint restores an archived (soft-deleted) supplier by ID.
      tags:
        - Suppliers
      operationId: restoreSupplier
      responses:
        '200':
          $ref: '#/components/responses/ShowSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/suppliers/{supplierId}/products:
    parameters:
      - $ref: '#/components/parameters/supplierId'
    get:
      summary: List products for a Supplier
      tags:
        - Suppliers
      operationId: listSupplierProducts
      description: |
        This endpoint retrieves a list of all the products for the given supplier.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSupplierProducts'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/products:
    get:
      summary: List Inventory Products
      tags:
        - InventoryProducts
      operationId: listInventoryProducts
      description: |
        This endpoint retrieves a list of all the inventory products for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-20'
        - $ref: '#/components/parameters/supplierIds'
        - $ref: '#/components/parameters/parameters_categoryIds'
        - $ref: '#/components/parameters/parameters_brandIds'
        - $ref: '#/components/parameters/parameters_query-12'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryProducts'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create an Inventory Product
      tags:
        - InventoryProducts
      operationId: createInventoryProduct
      description: |
        This endpoint creates an inventory product for the given site.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryProduct'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryProduct'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/products/{productId}:
    parameters:
      - $ref: '#/components/parameters/parameters_productId'
    get:
      summary: Show an Inventory Product
      tags:
        - InventoryProducts
      operationId: getInventoryProduct
      description: |
        This endpoint retrieves an inventory product for the given site.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProduct'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Inventory Product
      tags:
        - InventoryProducts
      operationId: updateInventoryProduct
      description: |
        This endpoint updates an inventory product for the given site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryProduct'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProduct'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an Inventory Product
      tags:
        - InventoryProducts
      operationId: deleteInventoryProduct
      description: |
        This endpoint deletes an inventory product for the given site.
      responses:
        '204':
          description: The inventory product was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/products/{productId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_productId'
    post:
      summary: Copy an Inventory Product
      description: |
        This endpoint copies an existing inventory product by ID.
      tags:
        - InventoryProducts
      operationId: actionInventoryProduct
      requestBody:
        $ref: '#/components/requestBodies/CopyInventoryProduct'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProduct'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/products/{productId}/adjustments:
    parameters:
      - $ref: '#/components/parameters/parameters_productId'
    get:
      summary: List adjustments for an Inventory Product
      tags:
        - InventoryProducts
      operationId: listInventoryProductAdjustments
      description: |
        This endpoint retrieves a list of all the adjustments for the given inventory product.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryProductAdjustments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an Inventory Product Adjustment
      tags:
        - InventoryProducts
      operationId: createInventoryProductAdjustment
      description: |
        This endpoint creates an adjustment for the given inventory product.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryProductAdjustment'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryProductAdjustment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/products/{productId}/supplier:
    parameters:
      - $ref: '#/components/parameters/parameters_productId'
    get:
      summary: Show an Inventory Product Supplier
      tags:
        - InventoryProducts
      operationId: getInventoryProductSupplier
      description: |
        This endpoint retrieves a supplier for an inventory product.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProductSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add a supplier to an Inventory Product
      tags:
        - InventoryProducts
      operationId: createInventoryProductSupplier
      description: |
        This endpoint adds a supplier to the given inventory product.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryProductSupplier'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryProductSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update an Inventory Product Supplier
      tags:
        - InventoryProducts
      operationId: updateInventoryProductSupplier
      description: |
        This endpoint updates the details of a supplier for an inventory product.
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryProductSupplier'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProductSupplier'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a supplier from an Inventory Product
      tags:
        - InventoryProducts
      operationId: deleteInventoryProductSupplier
      description: |
        This endpoint removes a supplier from an inventory product.
      responses:
        '204':
          description: The supplier was successfully removed from the inventory product.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/inventory-ids:
    get:
      summary: Stock on Hand report
      tags:
        - Reports
      operationId: listInventoryIds
      description: |
        This endpoint provides a list of all category, brand, supplier and inventory product IDs for the current site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-21'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryIds'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /inventory/inventory-ids/queue:
    get:
      summary: Queue an export of inventory IDs
      tags:
        - Reports
      operationId: actionQueueInventoryIdsExport
      description: |
        This endpoint queues an export of the inventory IDs report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-21'
      responses:
        '200':
          description: The request to queue the report was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /inventory/orders:
    get:
      summary: List Inventory Orders
      tags:
        - InventoryOrders
      operationId: listInventoryOrders
      description: |
        This endpoint retrieves a list of all the inventory orders for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-20'
        - $ref: '#/components/parameters/purchaseOrderNumber'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryOrders'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create an Inventory Order
      tags:
        - InventoryOrders
      operationId: createInventoryOrder
      description: |
        This endpoint creates an inventory order for the given site.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryOrder'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/orders/{orderId}:
    parameters:
      - $ref: '#/components/parameters/orderId'
    get:
      summary: Show an Inventory Order
      tags:
        - InventoryOrders
      operationId: getInventoryOrder
      description: |
        This endpoint retrieves an inventory order for the given site.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Inventory Order
      tags:
        - InventoryOrders
      operationId: updateInventoryOrder
      description: |
        This endpoint updates an inventory order for the given site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryOrder'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an Inventory Order
      tags:
        - InventoryOrders
      operationId: deleteInventoryOrder
      description: |
        This endpoint deletes an inventory order for the given site.
      responses:
        '204':
          description: The inventory order was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/orders/{orderId}/submit:
    parameters:
      - $ref: '#/components/parameters/orderId'
    post:
      summary: Submit an Inventory Order
      tags:
        - InventoryOrders
      operationId: createInventoryOrderSubmission
      description: |
        This endpoint submits an inventory order for the given site.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryOrderWithItems'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/orders/{orderId}/receive:
    parameters:
      - $ref: '#/components/parameters/orderId'
    post:
      summary: Receive an Inventory Order
      tags:
        - InventoryOrders
      operationId: createInventoryOrderReceipt
      description: |
        This endpoint receives an inventory order for the given site.
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryOrderWithItems'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/orders/{orderId}/items:
    parameters:
      - $ref: '#/components/parameters/orderId'
    get:
      summary: List Inventory Order Items
      tags:
        - InventoryOrders
      operationId: listInventoryOrderItems
      parameters:
        - $ref: '#/components/parameters/parameters_brandIds-2'
        - $ref: '#/components/parameters/parameters_categoryIds-2'
      description: |
        This endpoint retrieves a list of all the items for the given inventory order.
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryOrderItems'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add an item to an Inventory Order
      tags:
        - InventoryOrders
      operationId: createInventoryOrderItem
      description: |
        This endpoint adds an item to an inventory order.
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryOrderItem'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryOrderItem'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/orders/{orderId}/items/{orderItemId}:
    parameters:
      - $ref: '#/components/parameters/orderId'
      - $ref: '#/components/parameters/orderItemId'
    put:
      summary: Update an Inventory Order Item
      tags:
        - InventoryOrders
      operationId: updateInventoryOrderItem
      description: |
        This endpoint updates an item for the given inventory order.
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryOrderItem'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryOrderItem'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an Inventory Order Item
      tags:
        - InventoryOrders
      operationId: deleteInventoryOrderItem
      description: |
        This endpoint deletes an item for the given inventory order.
      responses:
        '204':
          description: The inventory order item was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/orders/{orderId}/queue:
    get:
      summary: Export an Inventory Order
      tags:
        - InventoryOrders
      operationId: actionQueueInventoryOrderExport
      description: |
        This endpoint queues an export of an inventory order for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_orderId'
        - $ref: '#/components/parameters/parameters_siteId-22'
        - $ref: '#/components/parameters/parameters_brandIds-2'
        - $ref: '#/components/parameters/parameters_categoryIds-2'
      responses:
        '200':
          description: The request to queue the export of the `InventoryOrder` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes:
    get:
      summary: List Stocktakes
      tags:
        - StockTakes
      operationId: listStockTakes
      description: |
        This endpoint retrieves a list of all the stocktakes for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-23'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListStockTakes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a Stocktake
      tags:
        - StockTakes
      operationId: createStockTake
      description: |
        This endpoint creates a stocktake for the given site.
      requestBody:
        $ref: '#/components/requestBodies/CreateStockTake'
      responses:
        '201':
          $ref: '#/components/responses/ShowStockTake'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/stock-takes/{stockTakeId}:
    parameters:
      - $ref: '#/components/parameters/stockTakeId'
    get:
      summary: Show a Stocktake
      tags:
        - StockTakes
      operationId: getStockTake
      description: |
        This endpoint retrieves a stocktake for the given site.
      responses:
        '200':
          $ref: '#/components/responses/ShowStockTake'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Stocktake
      tags:
        - StockTakes
      operationId: updateStockTake
      description: |
        This endpoint updates a stocktake for the given site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateStockTake'
      responses:
        '200':
          $ref: '#/components/responses/ShowStockTake'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Stocktake
      tags:
        - StockTakes
      operationId: deleteStockTake
      description: |
        This endpoint deletes a stocktake for the given site.
      responses:
        '204':
          description: The stocktake was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes/{stockTakeId}/post:
    parameters:
      - $ref: '#/components/parameters/stockTakeId'
    post:
      summary: Post a Stocktake
      tags:
        - StockTakes
      operationId: createStockTakePosting
      description: |
        This endpoint posts a stocktake for the given site.
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes/{stockTakeId}/items:
    get:
      summary: List Stocktake Items
      tags:
        - StockTakes
      operationId: listStockTakeItems
      description: |
        This endpoint retrieves a list of all the items for the given stocktake.
      parameters:
        - $ref: '#/components/parameters/stockTakeId'
        - $ref: '#/components/parameters/parameters_brandIds-3'
        - $ref: '#/components/parameters/parameters_categoryIds-3'
        - $ref: '#/components/parameters/parameters_supplierIds'
        - $ref: '#/components/parameters/parameters_query-13'
        - $ref: '#/components/parameters/parameters_status-4'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListStockTakeItems'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes/{stockTakeId}/items/{stockTakeItemId}:
    parameters:
      - $ref: '#/components/parameters/stockTakeId'
      - $ref: '#/components/parameters/stockTakeItemId'
    put:
      summary: Update a Stocktake Item
      tags:
        - StockTakes
      operationId: updateStockTakeItem
      description: |
        This endpoint updates a stocktake item for the given stocktake.
      requestBody:
        $ref: '#/components/requestBodies/UpdateStockTakeItem'
      responses:
        '200':
          $ref: '#/components/responses/ShowStockTakeItem'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Stocktake Item
      tags:
        - StockTakes
      operationId: deleteStockTakeItem
      description: |
        This endpoint deletes a stocktake item for the given stocktake.
      responses:
        '204':
          description: The stocktake item was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes/{stockTakeId}/queue:
    get:
      summary: Export a Stocktake
      tags:
        - StockTakes
      operationId: actionQueueStockTakeExport
      description: |
        This endpoint queues an export of a stocktake for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_stockTakeId'
        - $ref: '#/components/parameters/parameters_siteId-24'
        - $ref: '#/components/parameters/parameters_brandIds-3'
        - $ref: '#/components/parameters/parameters_categoryIds-3'
        - $ref: '#/components/parameters/parameters_supplierIds'
        - $ref: '#/components/parameters/parameters_status-4'
      responses:
        '200':
          description: The request to queue the export of the `StockTake` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/reports/stock-on-hand:
    get:
      summary: Stock on Hand report
      tags:
        - StockOnHand
      operationId: listStockOnHand
      description: |
        This endpoint provides a report of stock on hand for the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-21'
        - $ref: '#/components/parameters/parameters_date-4'
        - $ref: '#/components/parameters/parameters_brandIds-4'
        - $ref: '#/components/parameters/parameters_categoryIds-4'
        - $ref: '#/components/parameters/parameters_supplierIds-2'
      responses:
        '200':
          $ref: '#/components/responses/ListStockOnHand'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /inventory/reports/stock-on-hand/queue:
    get:
      summary: Stock on Hand report queue
      tags:
        - StockOnHand
      operationId: getStockOnHandQueue
      description: |
        This endpoint queues an export of the report of stock on hand for the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-21'
        - $ref: '#/components/parameters/parameters_date-4'
        - $ref: '#/components/parameters/parameters_brandIds-4'
        - $ref: '#/components/parameters/parameters_categoryIds-4'
        - $ref: '#/components/parameters/parameters_supplierIds-2'
      responses:
        '200':
          description: The request to queue the report of `StockOnHand` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /inventory/reports/stock-adjustments:
    get:
      summary: Stock Adjustments report
      tags:
        - StockAdjustments
      operationId: listStockAdjustments
      description: |
        This endpoint provides a report of stock adjustments for the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-25'
        - $ref: '#/components/parameters/parameters_dateFrom-2'
        - $ref: '#/components/parameters/parameters_dateTo-2'
        - $ref: '#/components/parameters/parameters_brandIds-5'
        - $ref: '#/components/parameters/parameters_categoryIds-5'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListStockAdjustments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /inventory/reports/stock-adjustments/queue:
    get:
      summary: Stock Adjustments report queue
      tags:
        - StockAdjustments
      operationId: actionQueueStockAdjustments
      description: |
        This endpoint queues an export of the report of stock adjustments for the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-25'
        - $ref: '#/components/parameters/parameters_dateFrom-2'
        - $ref: '#/components/parameters/parameters_dateTo-2'
        - $ref: '#/components/parameters/parameters_brandIds-5'
        - $ref: '#/components/parameters/parameters_categoryIds-5'
      responses:
        '200':
          description: The request to queue the report of `StockAdjustments` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/appointment-enquiries/{appointmentEnquiryId}/confirm:
    parameters:
      - $ref: '#/components/parameters/appointmentEnquiryId'
    post:
      summary: Confirm an enquiry using the start time provided.
      tags:
        - AppointmentEnquiries
      description: Use this endpoint to confirm an appointment enquiry
      operationId: actionConfirmAppointmentEnquiry
      requestBody:
        $ref: '#/components/requestBodies/ConfirmAppointmentEnquiryRequest'
      responses:
        '200':
          $ref: '#/components/responses/AppointmentEnquiryResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/coupons:
    get:
      summary: List coupons
      tags:
        - Coupons
      operationId: listCoupons
      description: |
        This endpoint lists coupons for an organisation. By default, only manual redemption coupons are returned.
        Use the `redemption_type` filter to retrieve programmatic coupons (credit types).
      parameters:
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/redemptionType'
      responses:
        '200':
          $ref: '#/components/responses/ListCoupons'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a coupon
      tags:
        - Coupons
      operationId: createCoupon
      description: This endpoint creates a new coupon for an organisation.
      requestBody:
        $ref: '#/components/requestBodies/CreateCoupon'
      responses:
        '201':
          $ref: '#/components/responses/ShowCoupon'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/coupons/{couponId}:
    parameters:
      - $ref: '#/components/parameters/couponId'
    get:
      summary: Get a single coupon
      tags:
        - Coupons
      operationId: getCoupon
      description: This endpoint retrieves a single coupon by its ID.
      responses:
        '200':
          $ref: '#/components/responses/ShowCoupon'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a coupon
      tags:
        - Coupons
      operationId: updateCoupon
      description: This endpoint updates a coupon.
      requestBody:
        $ref: '#/components/requestBodies/UpdateCoupon'
      responses:
        '200':
          $ref: '#/components/responses/ShowCoupon'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Soft-delete a coupon
      tags:
        - Coupons
      operationId: deleteCoupon
      description: |
        Soft-deletes a coupon. The coupon stops issuing new discounts but
        any existing `OrderDiscount`s created from it remain in place. Use
        `POST /shop/coupons/{couponId}/restore` to bring it back.
      responses:
        '200':
          $ref: '#/components/responses/ShowCoupon'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/coupons/{couponId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/couponId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a Coupon
      description: Returns the localised `name` and `description` for the given locale.
      operationId: getCouponLocaleStrings
      tags:
        - Coupons
      responses:
        '200':
          $ref: '#/components/responses/ShowCouponLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a Coupon
      description: Sets the localised `name` and/or `description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateCouponLocaleStrings
      tags:
        - Coupons
      requestBody:
        $ref: '#/components/requestBodies/UpdateCouponLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateCouponLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/coupons/{couponId}/codes:
    parameters:
      - $ref: '#/components/parameters/couponId'
    get:
      summary: List codes for a coupon
      description: |
        Returns a paginated list of `CouponCode`s belonging to the given
        `Coupon`. Use this to inspect which codes have been generated,
        their validity windows, and whether they've been pre-allocated to
        specific customers.

        Requires the `RESERVATIONS_VIEW` permission on the coupon's site.
      operationId: listCouponCodes
      tags:
        - CouponCodes
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCouponCodes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a coupon code
      description: |
        Generates a new `CouponCode` under the parent `Coupon`. All body
        fields are optional — pass `code` to set a specific string, omit
        to auto-generate. Set `valid_from_date`/`valid_to_date` to
        time-limit the code, `multi_use` to allow multiple redemptions,
        and `customer_credit_id` + `customer_id` to pre-allocate it.

        Requires the `SETTINGS_MANAGE` permission on the coupon's site.
        Returns 422 if `code` collides with another code under the same
        coupon (codes are unique per coupon, not globally).
      operationId: createCouponCode
      tags:
        - CouponCodes
      requestBody:
        $ref: '#/components/requestBodies/CreateCouponCode'
      responses:
        '201':
          $ref: '#/components/responses/ShowCouponCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/coupons/{couponId}/codes/{couponCodeId}:
    parameters:
      - $ref: '#/components/parameters/couponId'
      - $ref: '#/components/parameters/parameters_couponCodeId'
    get:
      summary: Retrieve a coupon code
      description: |
        Returns a single `CouponCode` by ID, scoped to its parent `Coupon`.
        Use this to inspect a specific code's validity window or
        pre-allocation.

        Requires the `RESERVATIONS_VIEW` permission on the coupon's site.
      operationId: getCouponCode
      tags:
        - CouponCodes
      responses:
        '200':
          $ref: '#/components/responses/ShowCouponCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Delete a coupon code
      description: |
        Removes a `CouponCode`. Past redemptions are unaffected — the
        customer credit issued at redemption time persists. Future
        attempts to use the code fail with a 422.

        Requires the `SETTINGS_MANAGE` permission on the coupon's site.
      operationId: deleteCouponCode
      tags:
        - CouponCodes
      responses:
        '204':
          description: Coupon code deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/coupons/{couponId}/copy:
    parameters:
      - $ref: '#/components/parameters/couponId'
    post:
      summary: Duplicate a coupon
      description: |
        Creates a copy of an existing `Coupon`. Useful when seeding a
        similar coupon (e.g. a renewal of a seasonal promotion, or a
        sibling coupon scoped to a different segment). The copy inherits
        every field from the source; rename it via a subsequent
        `PUT /shop/coupons/{couponId}`.

        Requires the `copy` permission on the source `Coupon` (see
        `resourceAbilityMap` on `CouponController`). No request body.
      operationId: copyCoupon
      tags:
        - Coupons
      responses:
        '201':
          $ref: '#/components/responses/ShowCoupon'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/coupons/{couponId}/restore:
    parameters:
      - $ref: '#/components/parameters/couponId'
    post:
      summary: Restore a deleted coupon
      description: |
        Un-deletes a previously soft-deleted `Coupon`. The coupon returns
        to its pre-deletion state, including code, value, validity
        window, and offering discounts. Past orders that redeemed the
        coupon remain unaffected.

        Requires the `restore` permission on the `Coupon`. No request body.
      operationId: restoreCoupon
      tags:
        - Coupons
      responses:
        '200':
          $ref: '#/components/responses/ShowCoupon'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/coupons/{couponId}/offering-discounts:
    post:
      summary: Add an offering discount to a coupon
      tags:
        - Coupons
      operationId: createOfferingDiscount
      description: This endpoint adds an offering discount to a coupon.
      parameters:
        - $ref: '#/components/parameters/couponId'
      requestBody:
        $ref: '#/components/requestBodies/CreateOfferingDiscount'
      responses:
        '201':
          $ref: '#/components/responses/ShowOfferingDiscount'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/coupons/{couponId}/offering-discounts/{offeringDiscountId}:
    parameters:
      - $ref: '#/components/parameters/couponId'
      - $ref: '#/components/parameters/offeringDiscountId'
    put:
      summary: Update an offering discount for a coupon
      tags:
        - Coupons
      operationId: updateOfferingDiscount
      description: This endpoint updates an offering discount for a coupon.
      requestBody:
        $ref: '#/components/requestBodies/UpdateOfferingDiscount'
      responses:
        '200':
          $ref: '#/components/responses/ShowOfferingDiscount'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an offering discount from a coupon
      tags:
        - Coupons
      operationId: deleteCouponOfferingDiscount
      description: |
        Removes an offering-discount association from a `Coupon`. The
        coupon itself is unaffected — only the discount on the specified
        offering is removed. Requires the `SETTINGS_MANAGE` permission on
        the coupon's site.
      responses:
        '204':
          description: Offering discount removed successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/coupon-codes/{code}/usage-stats:
    parameters:
      - $ref: '#/components/parameters/parameters_code-3'
    get:
      summary: Get coupon code usage statistics
      tags:
        - CouponCodes
      description: Gets the usage statistics for a coupon code at a specific booking date. Returns null data if the coupon has no usage limits configured.
      operationId: getCouponCodeUsageStats
      parameters:
        - $ref: '#/components/parameters/bookingDate'
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/parameters_offeringId-3'
      responses:
        '200':
          $ref: '#/components/responses/CouponCodeUsageStatsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/fiscal-receipts/{receiptId}:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscal-receipts/{receiptId}/document:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscal-receipts/{receiptId}/document/email:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscal-receipts/{receiptId}/document/reissue:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscal-receipts/{receiptId}/document/printed:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscal-receipts/{receiptId}/reprint:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscal-receipts/{receiptId}/retry:
    parameters:
      - $ref: '#/components/parameters/receiptId'
  /shop/fiscalisation-actions/{actionId}:
    parameters:
      - $ref: '#/components/parameters/actionId'
  /shop/fiscalisation-actions/{actionId}/retry:
    parameters:
      - $ref: '#/components/parameters/actionId'
  /shop/fiscalisation-journal-events/{event}:
    parameters:
      - $ref: '#/components/parameters/eventId'
  /shop/fiscalisation-journal-events/{event}/retry:
    parameters:
      - $ref: '#/components/parameters/eventId'
  /shop/orders:
    get:
      summary: Retrieve all orders matching the given parameters
      tags:
        - Orders
      operationId: listOrders
      description: Use this endpoint to retrieve orders
      parameters:
        - $ref: '#/components/parameters/parameters_query-14'
        - $ref: '#/components/parameters/customerId'
        - $ref: '#/components/parameters/parameters_status-5'
        - $ref: '#/components/parameters/labels'
        - $ref: '#/components/parameters/itemOfferingId'
        - $ref: '#/components/parameters/itemOfferingType'
        - $ref: '#/components/parameters/submittedById'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-2'
        - $ref: '#/components/parameters/parameters_revenueDateTo-2'
        - $ref: '#/components/parameters/itemDate'
        - $ref: '#/components/parameters/parameters_itemDateFrom'
        - $ref: '#/components/parameters/parameters_itemDateTo'
        - $ref: '#/components/parameters/itemStatus'
        - $ref: '#/components/parameters/submittedAtFrom'
        - $ref: '#/components/parameters/submittedAtTo'
        - $ref: '#/components/parameters/updatedAtFrom'
        - $ref: '#/components/parameters/updatedAtTo'
        - $ref: '#/components/parameters/isMembership'
        - $ref: '#/components/parameters/hasOutstandingBalance'
        - $ref: '#/components/parameters/salesChannel'
        - $ref: '#/components/parameters/externalId'
        - $ref: '#/components/parameters/genericItemsArray'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListOrders'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a new order
      tags:
        - Orders
      operationId: createOrder
      description: |
        Create a new order in the `new` or `in_progress` state. An order is the
        server-side representation of a basket — items, guests, discounts,
        payments and so on hang off it via the sub-resources documented under
        `/shop/orders/{orderId}/*`. The freshly created order is empty: callers
        typically follow this call with one or more `POST
        /shop/orders/{orderId}/items` requests and finally `POST
        /shop/orders/{orderId}/submit` to convert the order from a basket into
        a confirmed sale.

        The `site_id` is required and must be a site the caller has permission
        to create orders for. If `customer_id` is provided, the customer is
        attached to the order immediately — equivalent to a follow-up call to
        `POST /shop/orders/{orderId}/customer`. `external_ref` and
        `external_ids` capture identifiers from the calling system (e.g. a PMS
        reservation reference) so the order can be reconciled later.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrder'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/queue:
    get:
      summary: Queue an export of the orders list
      tags:
        - Orders
      operationId: actionQueueOrdersList
      description: Queue a request to export the orders list
      parameters:
        - $ref: '#/components/parameters/parameters_query-14'
        - $ref: '#/components/parameters/customerId'
        - $ref: '#/components/parameters/parameters_status-5'
        - $ref: '#/components/parameters/labels'
        - $ref: '#/components/parameters/itemOfferingId'
        - $ref: '#/components/parameters/itemOfferingType'
        - $ref: '#/components/parameters/submittedById'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-2'
        - $ref: '#/components/parameters/parameters_revenueDateTo-2'
        - $ref: '#/components/parameters/itemDate'
        - $ref: '#/components/parameters/parameters_itemDateFrom'
        - $ref: '#/components/parameters/parameters_itemDateTo'
        - $ref: '#/components/parameters/itemStatus'
        - $ref: '#/components/parameters/submittedAtFrom'
        - $ref: '#/components/parameters/submittedAtTo'
        - $ref: '#/components/parameters/updatedAtFrom'
        - $ref: '#/components/parameters/updatedAtTo'
        - $ref: '#/components/parameters/isMembership'
        - $ref: '#/components/parameters/hasOutstandingBalance'
        - $ref: '#/components/parameters/salesChannel'
        - $ref: '#/components/parameters/externalId'
        - $ref: '#/components/parameters/parameters_siteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/orders/{orderId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Retrieve a single order
      tags:
        - Orders
      operationId: getOrder
      description: Use this endpoint to retrieve a single orders
      parameters:
        - $ref: '#/components/parameters/genericItemsArray'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an order
      tags:
        - Orders
      operationId: updateOrder
      description: |
        Update mutable fields on an existing order. Used for in-progress
        edits — attaching or swapping a customer, recording contact
        details against the order, advancing the basket stage, and so on.

        `customer_id` is interpreted specially. Passing a string ID
        attaches that customer to the order (subject to availability and
        brand checks); passing `null` removes the current customer.

        If `stage` is the only field supplied, the order takes a fast
        path that just records the new stage and returns — useful for
        keeping live dashboards in sync without re-running the full
        update pipeline.

        `metadata` uses merge semantics: existing keys not mentioned in
        the request stay in place, keys passed with a value are upserted,
        and keys passed with `null` are removed.

        `special_requests` is writable only by users that hold the
        `SETTINGS_MANAGE` permission; for everyone else the field is
        silently dropped before validation.
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrder'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Cancel an order
      description: |
        Cancels the order. Each line item is cancelled in turn — bookings
        (appointments, area bookings, sessions, table reservations) are
        cancelled and any held resources released; purchases (vouchers,
        memberships, retail products) are voided; and any package items
        follow the cancellation rules of their underlying components.
        Payments remain attached to the order so they can be refunded
        separately via `POST /shop/orders/{orderId}/payments/{paymentId}`
        or absorbed into a credit note.

        The cancellation is reversible for a short window via `POST
        /shop/orders/{orderId}/restore`; once the order has aged past
        that window or been settled, the only path back is to create a
        fresh order.
      tags:
        - Orders
      operationId: deleteOrder
      responses:
        '204':
          description: The order was cancelled successfully.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Restore a cancelled order
      description: |
        Un-cancels a previously cancelled `Order`. The order returns to
        its pre-cancellation state — its items become live again, line-item
        payments and discounts persist, and any associated visits/bookings
        are re-activated. Permissions: requires the caller to have the
        `cancel` ability on the order (the same permission used to cancel
        in the first place).

        Use case: cancellation-by-mistake, customer change of mind shortly
        after cancellation, or a billing system mis-cancel that needs to
        be undone before the customer notices. For long-cancelled orders
        use the `OrderService` directly — restore expects a recent
        cancellation.
      operationId: restoreOrder
      tags:
        - Orders
      responses:
        '200':
          description: The order was restored successfully.
          content:
            application/json:
              schema:
                title: RestoreOrderResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/OrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/print-pos-receipt:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Print POS receipt
      description: |
        Use this endpoint to print a summary of the given order to an Esc/Pos printer connected to Trybe via a [`EscPosConnector`](/endpoints/shop/esc-pos-connectors/#createEscPosConnector).
      tags:
        - Orders
      operationId: actionPrintPosReceiptForOrder
      requestBody:
        $ref: '#/components/requestBodies/PrintPosReceiptForOrder'
      responses:
        '200':
          $ref: '#/components/responses/PrintPosReceiptForOrderResponse'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/payments:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Get all payments for an order
      tags:
        - Orders
      operationId: listOrderPayments
      description: |
        Use this endpoint to retrieve all the payments made for an order.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderPayments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add a payment to an order
      tags:
        - Orders
      operationId: createOrderPayment
      description: |
        Record a payment against an order. Use this endpoint to attach a manual
        payment — for example a cash payment taken at the front desk, a bank
        transfer that has cleared, or a card transaction taken via a terminal
        that is not integrated with Trybe.

        The `amount` must be greater than zero, expressed in the lowest
        denomination of the order's currency (pennies for `GBP`, cents for
        `USD`, and so on). The created payment is returned in the `data`
        envelope along with its assigned `id`, status, and refundable amount.

        Returns `400 Bad Request` if the payment can't be added — for example
        because the amount exceeds the outstanding balance, or the order is
        in a state that no longer accepts new payments.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderPayment'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrderPayment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/payments/{paymentId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_paymentId-2'
    get:
      summary: Retrieve a payment for an order
      tags:
        - Orders
      operationId: getOrderPayment
      description: |
        Use this endpoint to retrieve a single payment recorded against an order.
        The response includes the payment's current status, refundable amount,
        and any associated refunds or chargebacks — useful for reconciling the
        order's outstanding balance or surfacing payment details in a
        back-office view.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderPayment'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Remove a payment from an order
      tags:
        - Orders
      operationId: deleteOrderPayment
      description: |
        Remove a payment that has not yet been completed. Only payments that
        are still `pending` or that exist solely to store a payment method
        (`payment_method_stored`) can be removed — completed, captured, or
        refunded payments must be reversed via a refund instead.

        Returns `400 Bad Request` if the payment is in a state that cannot be
        removed. On success the updated `Order` is returned with the payment
        no longer attached.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrder'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/posting-room:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Attach a posting room from an order
      description: |
        Use this endpoint to attach a posting room to an order.
      tags:
        - Orders
      operationId: actionAttachPostingRoomToOrder
      requestBody:
        $ref: '#/components/requestBodies/PostingRoomToOrder'
      responses:
        '200':
          $ref: '#/components/responses/ShowPostingRoom'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Detach a posting room from an order
      description: |
        Use this endpoint to detach a posting room to an order.
      tags:
        - Orders
      operationId: actionDetachPostingRoomToOrder
      responses:
        '204':
          description: |
            The posting room was successfully detached from the order.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/discounts:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Apply a discount to an order
      description: |
        Use this endpoint to apply the discount from a [`DiscountType`](/endpoints/DiscountTypes) to an order.
      tags:
        - Orders
      operationId: createDiscountForOrder
      requestBody:
        $ref: '#/components/requestBodies/ApplyDiscountToOrder'
      responses:
        '201':
          $ref: '#/components/responses/ApplyOrderDiscount'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/discounts/{discountId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/discountId'
    delete:
      summary: Remove a discount from an order
      description: |
        This endpoint deletes a `Discount` by ID from an order.
      tags:
        - Orders
      operationId: deleteOrderDiscount
      responses:
        '204':
          description: The order discount was successfully deleted.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/emails:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List the emails sent for an order
      tags:
        - Orders
      operationId: listOrderEmails
      description: |
        Retrieve a paginated list of every email message that has been sent in
        relation to an order. Each entry includes delivery, open and bounce
        status; use [Retrieve an order email](#operation/getOrderEmail) to fetch
        the rendered HTML body for an individual message.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderEmails'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Send an email for an order
      tags:
        - Orders
      operationId: createOrderEmail
      description: |
        Send an email to the customer for an order. The `type` field selects which
        templated mailable is rendered — for example `BookingConfirmation` or
        `BookingReminder`. The list of available types is determined by the
        mailables configured in the application.

        To render the email without actually sending it, use the
        [Preview an order email](#operation/createOrderEmailPreview) endpoint
        instead.
      requestBody:
        $ref: '#/components/requestBodies/SendOrderEmail'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrderEmailSummary'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/emails/preview:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Preview an order email
      tags:
        - Orders
      operationId: createOrderEmailPreview
      description: |
        Render an email for an order without actually sending it. Useful for
        showing users a preview of the message that will be sent — for example
        in the order detail UI before confirming a manual send.
      requestBody:
        $ref: '#/components/requestBodies/PreviewOrderEmail'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderEmailMessage'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/emails/{emailId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/emailId'
    get:
      summary: Retrieve an order email
      tags:
        - Orders
      operationId: getOrderEmail
      description: |
        Retrieve the full rendered email message — including its HTML body —
        that was sent for an order. To get just the summary metadata for every
        email on the order, use [List the emails sent for an order](#operation/listOrderEmails)
        instead.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderEmailMessage'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Delete an order email
      tags:
        - Orders
      operationId: deleteOrderEmail
      description: |
        Remove the local record of an email message from the order. This does not
        recall the underlying email from the customer's inbox.
      responses:
        '204':
          description: The email message record was successfully deleted.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/external-ids:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    put:
      summary: Update an order's external IDs
      description: |
        Use this endpoint to update one or more of an order's external IDs
      tags:
        - Orders
      operationId: updateOrderExternalIds
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderExternalIds'
      responses:
        '200':
          $ref: '#/components/responses/OrderExternalIds'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/fiscal-receipts:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Retrieve all fiscal receipts attached to an order.
      description: Retrieve all fiscal receipts attached to an order.
      tags:
        - Orders
      operationId: listOrderFiscalReceipts
      responses:
        '200':
          $ref: '#/components/responses/OrderFiscalReceipts'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/guests:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List the guests on an order
      tags:
        - Orders
      operationId: listOrderGuests
      description: |
        Retrieve every guest attached to an order. The lead booker is the guest
        with `is_lead_booker` set to `true` — there is at most one lead booker
        per order.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderGuests'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add a guest to an order
      tags:
        - Orders
      operationId: createOrderGuest
      description: |
        Add a new guest to an order. If this is the first guest on the order, all
        existing items will be reassigned to the new guest and they will be marked
        as the lead booker by default.

        If the order doesn't yet have a `customer_id` and the new guest is linked
        to a customer via `customer_id`, that customer is also set as the order's
        customer.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderGuest'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrderGuest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/guests/{guestId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_guestId'
    put:
      summary: Update a guest on an order
      tags:
        - Orders
      operationId: updateOrderGuest
      description: |
        Update the details of a guest already attached to an order. Linking the
        guest to a customer via `customer_id` overwrites the guest's `first_name`,
        `last_name`, `name` and `email` with the customer's profile values, and
        transfers any existing visit intake form submission to that customer.
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderGuest'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderGuest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a guest from an order
      tags:
        - Orders
      operationId: deleteOrderGuest
      description: |
        Remove a guest from an order. Any items currently assigned to this guest
        are unassigned, and the order totals are recalculated.
      responses:
        '204':
          description: The guest was successfully removed from the order.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/items:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Add an item to an order
      description: Use this endpoint to add an item to an existing order.
      tags:
        - Orders
      operationId: createOrderItem
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderItem'
      responses:
        '200':
          $ref: '#/components/responses/OrderItem'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/items/{itemId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
    put:
      summary: Update an order item
      description: |
        Use this endpoint to update an item on an existing order. The
        fields you can update depend on the item's `item_type` — for
        bookings you can change the date, time, duration and resources
        (practitioner, room, equipment, area); for purchases you can
        change the quantity and any item-type specific configuration on
        `item_configuration`; for packages you can swap out package
        choices via `package_items`.

        Most fields are optional — only the values you include in the
        payload are changed. If the requested change would breach
        availability rules a `400` response is returned unless the
        authenticated user has the `reservations:override_rules`
        permission and you pass `skip_availability_checks=true`.
      tags:
        - Orders
      operationId: updateOrderItem
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderItem'
      responses:
        '200':
          $ref: '#/components/responses/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove an item from an order
      description: |
        Use this endpoint to remove a line item from an order. If the
        item is a booking (appointment, area booking, session, table
        reservation) the underlying booking is cancelled and any held
        resources are released. The order's totals are recalculated
        immediately.
      tags:
        - Orders
      operationId: deleteOrderItem
      responses:
        '204':
          description: The item was successfully removed from the order.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/items/{itemId}/discounts:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
    post:
      summary: Apply a discount to an order item
      description: |
        Use this endpoint to apply the discount from a [`DiscountType`](/endpoints/DiscountTypes) to an order item.
      tags:
        - Orders
      operationId: createDiscountForOrderItem
      requestBody:
        $ref: '#/components/requestBodies/ApplyDiscountToOrderItem'
      responses:
        '201':
          $ref: '#/components/responses/ApplyOrderItemDiscount'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/items/{itemId}/discounts/{discountId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-3'
      - $ref: '#/components/parameters/parameters_itemId'
      - $ref: '#/components/parameters/parameters_discountId'
    delete:
      summary: Remove a discount from an order item
      description: |
        This endpoint deletes a `Discount` by ID from an order item.
      tags:
        - Orders
      operationId: deleteItemDiscount
      responses:
        '204':
          description: The item discount was successfully deleted.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/items/{itemId}/sold-by:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
    put:
      summary: Update the 'sold by' staff member for an item
      description: |
        Use this endpoint to update the 'sold by' (commission) attribute for an order item.
      tags:
        - Orders
      operationId: updateItemSoldBy
      requestBody:
        $ref: '#/components/requestBodies/UpdateItemSoldBy'
      responses:
        '201':
          $ref: '#/components/responses/OrderItem'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/labels:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Update the labels on an order
      description: Use this endpoint to replace all labels on an order with the given values.
      tags:
        - Orders
      operationId: updateOrderLabels
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderLabels'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/labels/{labelId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/labelId'
    put:
      summary: Add a single label to an order
      description: |
        Attaches the given `Label` to the order. If the label is already
        attached the request is a no-op and the endpoint still returns
        `201`. The label must belong to the same site as the order — a
        `422` is returned otherwise. Use this endpoint when you want to
        incrementally add a label without replacing the order's full
        label set (use `POST /shop/orders/{orderId}/labels` for the
        replace-all behaviour).
      tags:
        - Orders
      operationId: updateOrderLabel
      responses:
        '201':
          $ref: '#/components/responses/ShowOrderLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a single label from an order
      description: |
        Detaches the given `Label` from the order. If the label was not
        attached the request is a no-op. The label itself is not deleted
        — only its association with the order is removed.
      tags:
        - Orders
      operationId: deleteOrderLabel
      responses:
        '204':
          description: The label was successfully removed from the order.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/notes:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List the notes on an order
      tags:
        - Orders
      operationId: listOrderNotes
      description: |
        Retrieve every internal note attached to an order, ordered oldest-first.
        Notes are typically used by front-of-house and operations staff to capture
        requests or context that doesn't belong on the order itself — for example
        "guest is celebrating an anniversary" or "double room requested".
      responses:
        '200':
          $ref: '#/components/responses/ListOrderNotes'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add a note to an order
      tags:
        - Orders
      operationId: createOrderNote
      description: |
        Add a new note to an order. The note will be attributed to the authenticated
        user, who is recorded as the `created_by` user on the resulting `OrderNote`.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderNote'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrderNote'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/notes/{noteId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/noteId'
    get:
      summary: Retrieve an order note
      tags:
        - Orders
      operationId: getOrderNote
      description: |
        Retrieve a single note attached to an order.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderNote'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an order note
      tags:
        - Orders
      operationId: updateOrderNote
      description: |
        Replace the contents of an existing order note. The `created_by` user and
        `created_at` timestamp are preserved — only the body is updated.
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderNote'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderNote'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an order note
      tags:
        - Orders
      operationId: deleteOrderNote
      description: |
        Permanently remove a note from an order. This action cannot be undone.
      responses:
        '204':
          description: The order note was successfully deleted.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/remove-promo-code/{discountTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/discountTypeId'
    delete:
      summary: Remove promo code
      description: |
        Use this endpoint to remove the applied [`DiscountType`](/endpoints/DiscountTypes), when it is a promo code, from an order, as well as its associated discounts.
      tags:
        - Orders
      operationId: deletePromoCodeFromOrder
      responses:
        '204':
          description: The applied promo code was successfully removed
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/service-charge:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    put:
      summary: Update the service charge on an order
      description: Use this endpoint to update the service charge applied to an order.
      tags:
        - Orders
      operationId: updateOrderServiceCharge
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderServiceCharge'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/tip:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    put:
      summary: Update the tip on an order
      description: Use this endpoint to update the tip applied to an order.
      tags:
        - Orders
      operationId: updateOrderTip
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrderTip'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/tip/{tipId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/tipId'
    delete:
      summary: Remove a tip from an order
      description: Use this endpoint to remove a specific tip from an order.
      tags:
        - Orders
      operationId: deleteOrderTip
      responses:
        '200':
          $ref: '#/components/responses/ShowOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/order-messages:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List order messages
      tags:
        - Orders
      operationId: listOrderMessages
      description: |
        This endpoint retrieves all the SMS messages and emails relating to an order.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderMessages'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/automated-order-messages:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Retrieve the date which the next automated order message will be sent at
      tags:
        - Orders
      operationId: getNextAutomatedOrderMessage
      description: |
        This endpoint retrieves the date for when the next automated order message will be sent.
        This includes reminder and follow-up messages.
      responses:
        '200':
          $ref: '#/components/responses/GetNextAutomatedOrderMessage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/sms:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List SMS messages
      tags:
        - Orders
      operationId: listSmsMessages
      description: |
        This endpoint retrieves all the SMS messages relating to an order.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSmsMessages'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Send an SMS message
      tags:
        - Orders
      operationId: createSmsMessage
      description: |
        This endpoint sends an SMS message to a customer.
      requestBody:
        $ref: '#/components/requestBodies/SendSmsMessage'
      responses:
        '201':
          $ref: '#/components/responses/ShowSmsMessage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/sms/{smsId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/smsId'
    get:
      summary: Get a single SMS message
      tags:
        - Orders
      operationId: getSmsMessage
      description: |
        This endpoint retrieves a single SMS message relating to an order.
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsMessage'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Delete an SMS message
      tags:
        - Orders
      operationId: deleteSmsMessage
      description: |
        This endpoint deletes an SMS message relating to an order.
      responses:
        '204':
          description: The SMS message was successfully deleted
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/sms/preview:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Preview an SMS message for an order
      tags:
        - Orders
      operationId: createSmsMessagePreview
      description: |
        This endpoint previews an SMS message for an order.
      requestBody:
        $ref: '#/components/requestBodies/PreviewSmsMessage'
      responses:
        '201':
          $ref: '#/components/responses/PreviewSmsMessage'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/sms/suppress:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Retrieve the suppression status of an SMS message for an order
      tags:
        - Orders
      operationId: getSmsMessageSuppressionStatus
      description: |
        This endpoint retrieves the suppression status of a scheduled follow-up or reminder SMS message for an order.
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsMessageSuppressionStatus'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Manage SMS suppression for an order
      tags:
        - Orders
      operationId: createSmsMessageSuppression
      description: |
        This endpoint allows you to stop or start a scheduled follow-up or reminder SMS message from being sent for an order.
      requestBody:
        $ref: '#/components/requestBodies/SuppressSmsMessage'
      responses:
        '201':
          description: The SMS message was successfully suppressed
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/customer:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Add customer to an order
      description: Use this endpoint to add a customer to an order.
      tags:
        - Orders
      operationId: actionAddCustomerToOrder
      requestBody:
        $ref: '#/components/requestBodies/AddCustomerToOrder'
      responses:
        '201':
          $ref: '#/components/responses/CustomerSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/customer-credits:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Apply a customer credit to an order
      tags:
        - Orders
      operationId: createOrderCustomerCredit
      description: |
        Apply a customer credit balance to an order — for example, redeeming a
        refund credit or a gift balance held against the customer's profile.
        The updated `Order` is returned so the caller can see the new outstanding
        balance after the credit is deducted.

        Returns `400 Bad Request` if the credit can't be applied — for example
        because it has already been fully redeemed, belongs to a different
        customer, or is expired.
      requestBody:
        $ref: '#/components/requestBodies/ApplyCustomerCreditToOrder'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrder'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/customer-credits/{customerCreditId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_customerCreditId'
    delete:
      summary: Remove a customer credit from an order
      tags:
        - Orders
      operationId: deleteOrderCustomerCredit
      description: |
        Remove a previously-applied customer credit from an order. The credit's
        balance is refunded back to the customer's profile and the order totals
        are recalculated.
      responses:
        '204':
          description: The customer credit was successfully removed from the order.
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/payouts/{payoutId}/retry:
    parameters:
      - $ref: '#/components/parameters/payoutId'
  /shop/integration-configs/{integrationConfigId}:
    parameters:
      - $ref: '#/components/parameters/integrationConfigId'
  /shop/integration-configs/{integrationConfigId}/link:
    parameters:
      - $ref: '#/components/parameters/integrationConfigId'
        required: true
  /shop/integration-configs/{integrationConfigId}/enable:
    parameters:
      - $ref: '#/components/parameters/integrationConfigId'
        required: true
  /shop/integration-configs/{integrationConfigId}/disable:
    parameters:
      - $ref: '#/components/parameters/integrationConfigId'
        required: true
  /shop/organisations/{organisationId}/categories:
    get:
      summary: List Categories
      tags:
        - Organisations
      operationId: listOrganisationCategories
      description: |
        Returns an array of all categories the current user has permission to view.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
        - $ref: '#/components/parameters/voucherApplicable'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCategories'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a Category
      tags:
        - Organisations
      operationId: createOrganisationCategory
      description: |
        Create a new category that belongs to the given organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      requestBody:
        $ref: '#/components/requestBodies/CreateCategory'
      responses:
        '201':
          $ref: '#/components/responses/ShowCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/categories/order:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
    get:
      summary: List Categories In Order
      tags:
        - Organisations
      operationId: listOrganisationCategoryOrder
      description: |
        Returns all categories the current user has permission to view, in their
        persisted display order.
      parameters:
        - $ref: '#/components/parameters/voucherApplicable'
      responses:
        '200':
          $ref: '#/components/responses/OrderedCategories'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update Category Order
      tags:
        - Organisations
      operationId: updateOrganisationCategoryOrder
      description: |
        Persists the display order of categories. The position of each ID in the
        `category_ids` array is stored as that category's order.
      requestBody:
        $ref: '#/components/requestBodies/UpdateCategoryOrder'
      responses:
        '200':
          $ref: '#/components/responses/OrderedCategories'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/categories/order/all:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
    get:
      summary: List All Categories
      tags:
        - Organisations
      operationId: listAllOrganisationCategories
      description: |
        Returns every category belonging to the organisation in its persisted
        display order, regardless of `voucher_applicable`.
      responses:
        '200':
          $ref: '#/components/responses/OrderedCategories'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/categories/{categoryId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_categoryId-5'
    get:
      summary: Get Category
      tags:
        - Organisations
      operationId: getOrganisationCategory
      description: |
        Returns the details of a single category.
      responses:
        '200':
          $ref: '#/components/responses/ShowCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Category
      tags:
        - Organisations
      operationId: updateOrganisationCategory
      description: |
        Update an existing category.
      requestBody:
        description: Updates the specified `Category` object by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
        required: true
        content:
          application/json:
            schema:
              title: UpdateCategory
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  description: |
                    Display name of the category, shown to customers on the
                    storefront and to staff in the admin UI. Categories
                    group offerings (treatments, classes, products) for
                    navigation and reporting. 1-120 characters; must not
                    contain HTML.
                  example: Massages
                voucher_applicable:
                  type: boolean
                  description: |
                    Whether the category can be selected when issuing vouchers.
      responses:
        '200':
          $ref: '#/components/responses/ShowCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Category
      tags:
        - Organisations
      operationId: deleteOrganisationCategory
      description: |
        Delete the given category.
      responses:
        '204':
          description: The category was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/categories/{categoryId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_categoryId-5'
    post:
      summary: Copy a Category
      tags:
        - Organisations
      operationId: copyOrganisationCategory
      description: |
        Copies the given category. Any properties supplied in the request body
        will override the corresponding values on the new category.
      requestBody:
        description: Pass any category properties that should be overridden on the copied resource.
        required: false
        content:
          application/json:
            schema:
              title: CopyCategory
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  description: |
                    Display name to give the duplicated category. The new
                    category inherits the source's offerings and settings;
                    the name distinguishes the copy from the original.
                    1-120 characters; must not contain HTML.
                  example: Massages (Summer 2026)
                voucher_applicable:
                  type: boolean
                  description: |
                    Whether the new category can be selected when issuing vouchers.
      responses:
        '201':
          $ref: '#/components/responses/ShowCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/categories/{categoryId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_categoryId-5'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a Category
      description: Returns the localised `name` for the given locale.
      operationId: getCategoryLocaleStrings
      tags:
        - Organisations
      responses:
        '200':
          $ref: '#/components/responses/ShowCategoryLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a Category
      description: Sets the localised `name` for the given locale. Pass `null` to clear the translation and fall back to the default name.
      operationId: updateCategoryLocaleStrings
      tags:
        - Organisations
      requestBody:
        $ref: '#/components/requestBodies/UpdateCategoryLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateCategoryLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/custom-payment-types:
    get:
      summary: List custom payment types
      tags:
        - Organisations
      operationId: listOrganisationCustomPaymentTypes
      description: |
        Returns all `CustomPaymentType`s defined on the named
        `Organisation`. Custom payment types are shared across the
        organisation's `Site`s; assign them to individual sites via
        [`updateShopSite`](#operation/updateShopSite) using the
        `custom_payment_type_ids` field.

        The response is currently un-paginated — every custom payment type
        on the organisation is returned in one shot regardless of the
        `page` / `per_page` query parameters. The parameters are accepted
        (so a generic paginated-list helper can be pointed at this
        endpoint without special-casing) but treated as no-ops by the
        backend. Pass `per_page=-1` for the same effect.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomPaymentTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a custom payment type
      tags:
        - Organisations
      operationId: createOrganisationCustomPaymentType
      description: |
        Create a new `CustomPaymentType` on the named `Organisation`.

        The newly created payment type is not automatically enabled on
        any `Site` — add it to a site's `custom_payment_type_ids` via
        [`updateShopSite`](#operation/updateShopSite) to make it
        selectable at the till.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      requestBody:
        $ref: '#/components/requestBodies/CreateCustomPaymentType'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomPaymentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/custom-payment-types/{customPaymentTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/customPaymentTypeId'
    get:
      summary: Get a custom payment type
      tags:
        - Organisations
      operationId: getOrganisationCustomPaymentType
      description: |
        Returns the details of a single `CustomPaymentType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomPaymentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a custom payment type
      tags:
        - Organisations
      operationId: updateOrganisationCustomPaymentType
      description: |
        Update an existing `CustomPaymentType`. Changes apply immediately
        to every `Site` that has the payment type attached.
      requestBody:
        $ref: '#/components/requestBodies/UpdateCustomPaymentType'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomPaymentType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a custom payment type
      tags:
        - Organisations
      operationId: deleteOrganisationCustomPaymentType
      description: |
        Delete a `CustomPaymentType`. Trybe will also remove the payment
        type's ID from `custom_payment_type_ids` on every `Site` in the
        organisation, so the tender stops appearing at the till.

        Historical orders that recorded the payment type are preserved
        via soft-delete.
      responses:
        '204':
          description: The custom payment type was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/date-sets:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/from'
      - $ref: '#/components/parameters/limit'
    get:
      summary: Get a list of all date sets belonging to the organisation.
      description: Returns an array of all date sets the current user has permission to view.
      operationId: listDateSets
      tags:
        - Organisations
      responses:
        '200':
          description: |
            `DateSet`s were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListDateSetsResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/DateSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    post:
      summary: Create a new DateSet
      description: Use this endpoint to create a new `DateSet`.
      operationId: createDateSet
      tags:
        - Organisations
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: CreateDateSet
              allOf:
                - $ref: '#/components/schemas/patch-requestBody-content-application~1json-schema'
                - type: object
                  required:
                    - dates
                    - name
      responses:
        '201':
          description: The date set was successfully created.
          content:
            application/json:
              schema:
                title: CreateDateSetResponse
                type: object
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/date-sets/{dateSetId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/dateSetId'
    get:
      summary: Retrieve a DateSet
      description: Use this endpoint to retrieve a `DateSet`.
      operationId: getDateSet
      tags:
        - Organisations
      responses:
        '200':
          description: The date set details were successfully retrieved.
          content:
            application/json:
              schema:
                title: GetDateSetResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/DateSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    patch:
      summary: Update a DateSet
      description: Use this endpoint to update a `DateSet`.
      operationId: updateDateSet
      tags:
        - Organisations
      requestBody:
        description: Updates the specified `DateSet` object by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
        required: true
        content:
          application/json:
            schema:
              title: UpdateDateSet
              type: object
              additionalProperties: false
              properties:
                dates:
                  $ref: '#/components/schemas/dates'
                name:
                  $ref: '#/components/schemas/properties-name'
      responses:
        '201':
          description: The date set was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateDateSetResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/DateSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Replace a DateSet
      description: |
        Replaces the `name` and `dates` of a `DateSet` with the supplied
        values. Functionally equivalent to the `PATCH` route — both end
        up routed to the same handler — exposed as `PUT` for legacy API
        clients that prefer the verb's "full replacement" semantics. Any
        field omitted from the body is treated as unchanged, matching the
        PATCH behaviour.
      operationId: actionReplaceDateSet
      tags:
        - Organisations
      requestBody:
        description: Replaces the specified `DateSet` object by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
        required: true
        content:
          application/json:
            schema:
              title: ReplaceDateSet
              type: object
              additionalProperties: false
              properties:
                dates:
                  $ref: '#/components/schemas/dates'
                name:
                  $ref: '#/components/schemas/properties-name'
      responses:
        '200':
          description: The date set was successfully updated.
          content:
            application/json:
              schema:
                title: ReplaceDateSetResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/DateSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a DateSet
      description: |
        Permanently deletes the `DateSet`. The dates the set contained are
        no longer treated as restricted/special, but any bookings that were
        placed while the set was active remain unaffected.
      operationId: deleteDateSet
      tags:
        - Organisations
      responses:
        '204':
          description: The date set was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/recurrence-groups:
    get:
      summary: List SessionRecurrenceGroups
      tags:
        - SessionRecurrenceGroups
      operationId: listSessionRecurrenceGroups
      description: This endpoint lists all the `SessionRecurrenceGroups`.
      parameters:
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/recurrenceEndAfter'
        - $ref: '#/components/parameters/recurrenceEndBefore'
        - $ref: '#/components/parameters/sessionTypeId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
      responses:
        '200':
          description: The `SessionRecurrenceGroup`s were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListSessionRecurrenceGroups
                type: object
                additionalProperties: false
                required:
                  - data
                  - meta
                  - links
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SessionRecurrenceGroup'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      operationId: createSessionRecurrenceGroup
      summary: Create a new SessionRecurrenceGroup
      description: This endpoint creates a new `SessionRecurrenceGroup` for a `SessionType`.
      tags:
        - SessionRecurrenceGroups
      requestBody:
        description: To create a recurrence group you pass a `SessionRecurrenceGroupUpdate` object.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSessionRecurrenceGroup'
      responses:
        '201':
          description: The recurrence group was successfully created.
          content:
            application/json:
              schema:
                title: SessionRecurrenceGroupResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/SessionRecurrenceGroup'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/recurrence-groups/{recurrenceGroupId}:
    put:
      operationId: updateSessionRecurrenceGroup
      summary: Update a SessionRecurrenceGroup
      description: This endpoint updates a `SessionRecurrenceGroup`.
      tags:
        - SessionRecurrenceGroups
      parameters:
        - $ref: '#/components/parameters/recurrenceGroupId'
      requestBody:
        description: Updates the specified `SessionRecurrenceGroup` object by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSessionRecurrenceGroup'
      responses:
        '200':
          description: The recurrence group was successfully updated.
          content:
            application/json:
              schema:
                title: SessionRecurrenceGroupResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/SessionRecurrenceGroup'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      operationId: deleteSessionRecurrenceGroup
      summary: Archive a SessionRecurrenceGroup
      description: This endpoint archives a `SessionRecurrenceGroup`.
      tags:
        - SessionRecurrenceGroups
      parameters:
        - $ref: '#/components/parameters/recurrenceGroupId'
      responses:
        '204':
          description: The `SessionRecurrenceGroup` was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/recurrence-groups/{recurrenceGroupId}/check-destroy:
    parameters:
      - $ref: '#/components/parameters/recurrenceGroupId'
  /shop/recurrence-groups/{recurrenceGroupId}/check-update:
    parameters:
      - $ref: '#/components/parameters/recurrenceGroupId'
  /shop/recurrence-groups/{recurrenceGroupId}/check-update/cancelled:
    parameters:
      - $ref: '#/components/parameters/recurrenceGroupId'
  /shop/scheduling-issues/{schedulingIssueId}:
    parameters:
      - $ref: '#/components/parameters/schedulingIssueId'
  /shop/sessions:
    get:
      operationId: listSessions
      summary: List Sessions
      description: This endpoint lists all `Session`s.
      tags:
        - Sessions
      parameters:
        - $ref: '#/components/parameters/cancelled'
        - $ref: '#/components/parameters/parameters_id'
        - $ref: '#/components/parameters/includeBookings'
        - $ref: '#/components/parameters/includeCancelled'
        - $ref: '#/components/parameters/parameters_practitionerId-5'
        - $ref: '#/components/parameters/parameters_recurrenceGroupId'
        - $ref: '#/components/parameters/parameters_roomId-3'
        - $ref: '#/components/parameters/parameters_sessionTypeId'
        - $ref: '#/components/parameters/parameters_zoneId-4'
        - $ref: '#/components/parameters/parameters_date'
        - $ref: '#/components/parameters/dateFrom'
        - $ref: '#/components/parameters/dateTo'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/startTimeFrom'
        - $ref: '#/components/parameters/startTimeTo'
      responses:
        '200':
          description: The `Session`s were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListSessions
                type: object
                additionalProperties: false
                required:
                  - data
                  - links
                  - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/schemas_Session'
                  links:
                    $ref: '#/components/schemas/PaginationLinks'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/sessions/{sessionId}:
    parameters:
      - $ref: '#/components/parameters/parameters_includeBookings'
      - $ref: '#/components/parameters/sessionId'
    get:
      summary: Fetch a Session
      description: Returns a single `Session` model.
      operationId: getSession
      tags:
        - Sessions
      responses:
        '200':
          description: The `Session` was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetSession
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Session'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Session
      description: |
        Updates an in-flight `Session` occurrence — practitioner, room,
        times, capacity, waitlist behaviour. Only fields included in the
        request body are written; everything else is left unchanged.

        Note this updates a single occurrence rather than the underlying
        `SessionType` or `SessionRecurrenceGroup` — for repeating session
        changes use the recurrence-group endpoints instead.
      operationId: updateSession
      tags:
        - Sessions
      requestBody:
        description: The fields to update on the session occurrence.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/schemas_Session'
      responses:
        '200':
          description: The `Session` was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateSession
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Session'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Cancel a Session
      description: |
        Cancels a single `Session` occurrence. Any existing bookings on
        the session are notified per the site's session-cancellation
        settings; the session itself is soft-deleted so it can be
        restored (see `POST /shop/sessions/{sessionId}/restore`).
      operationId: deleteSession
      tags:
        - Sessions
      responses:
        '204':
          description: The session was successfully cancelled.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sessions/{sessionId}/restore:
    parameters:
      - $ref: '#/components/parameters/sessionId'
    post:
      summary: Restore a deleted session
      description: |
        Un-deletes a previously soft-deleted `Session`. The session returns
        to its pre-deletion state, including its slot on the calendar.
        Customers booked into the session before deletion are NOT
        automatically rebooked — their bookings remain cancelled.

        Requires the `SETTINGS_MANAGE` permission on the session's site.
        No request body.
      operationId: restoreSession
      tags:
        - Sessions
      responses:
        '200':
          description: The session was restored successfully.
          content:
            application/json:
              schema:
                title: RestoreSessionResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Session'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sessions/{sessionId}/waitlist:
    parameters:
      - $ref: '#/components/parameters/sessionId'
    get:
      summary: Fetch a Session's waitlist
      description: |
        Returns a support/admin-facing view of a `Session`'s waitlist: who
        is currently queued (in order), who has already been promoted off
        the waitlist, and the waitlist-related entries from the session
        log — so "why did X get in ahead of Y?" can be answered without a
        database query.

        Requires the `RESERVATIONS_VIEW` permission on the session's site.
      operationId: getSessionWaitlist
      tags:
        - Sessions
      responses:
        '200':
          description: The session's waitlist was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetSessionWaitlist
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/SessionWaitlist'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/session-types:
    get:
      summary: List session types
      tags:
        - SessionTypes
      operationId: listSessionTypes
      description: |
        Returns a paginated list of `SessionType`s configured at the given site,
        matching the optional `query` substring. Use this to populate admin
        settings or a shopfront browse page. Pass `include_recurrence_groups=true`
        (the default) to embed each session type's recurrence relations alongside
        the data — useful when you also want to render upcoming sessions.
      parameters:
        - $ref: '#/components/parameters/parameters_query-15'
        - $ref: '#/components/parameters/include_recurrence_groups'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSessionTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a session type
      tags:
        - SessionTypes
      operationId: createSessionType
      description: |
        Creates a new `SessionType` at the caller's current site. Sessions
        are recurring offerings that run on a schedule (yoga classes, fitness
        sessions, group treatments). Once created, attach a `SessionRecurrenceGroup`
        to drive when occurrences happen.

        Requires the `SETTINGS_MANAGE` permission on the site.
      requestBody:
        $ref: '#/components/requestBodies/CreateSessionType'
      responses:
        '201':
          description: The session type was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-types/{sessionTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
    get:
      summary: Retrieve a session type
      description: |
        Returns the full `SessionType` model for the given ID. Use this to
        populate an admin edit screen or to look up settings when building
        a booking against a known session type.
      operationId: getSessionType
      tags:
        - SessionTypes
      responses:
        '200':
          description: The session type details were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a session type
      description: |
        Partially updates a `SessionType`. Every field is optional; only
        fields you send are written. Omitted fields retain their current
        values. Requires the `SETTINGS_MANAGE` permission on the session
        type's site.
      operationId: updateSessionType
      tags:
        - SessionTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateSessionType'
      responses:
        '200':
          description: The session type was updated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a session type
      description: |
        Soft-deletes a `SessionType`. Future session occurrences are no
        longer offered; existing bookings are unaffected. Use
        `POST .../restore` to bring it back.

        Requires the `SETTINGS_MANAGE` permission on the session type's
        site.
      operationId: deleteSessionType
      tags:
        - SessionTypes
      responses:
        '204':
          description: Session type deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/session-types/{sessionTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
    post:
      summary: Copy a session type
      description: |
        Duplicate an existing `SessionType` to bootstrap a near-identical
        variant. Any properties supplied in the request body override the
        source values on the copy. Use the `include_price_rules` and
        `include_recurrence_groups` query parameters to opt in to copying
        those related collections; by default only the core session type is
        duplicated.
      operationId: copySessionType
      tags:
        - SessionTypes
      parameters:
        - $ref: '#/components/parameters/includePriceRules'
        - $ref: '#/components/parameters/includeRecurrenceGroups'
      requestBody:
        description: Pass any session type properties that should be overridden on the copied resource.
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionType'
      responses:
        '201':
          description: The SessionType was successfully copied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-types/{sessionTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
    post:
      summary: Restore a deleted session type
      description: |
        Un-deletes a previously soft-deleted `SessionType`. Past bookings
        are unaffected by either the delete or the restore; future session
        occurrences resume being offered once active recurrence groups
        are restored too.

        Requires the `SETTINGS_MANAGE` permission on the session type's
        site. No request body.
      operationId: restoreSessionType
      tags:
        - SessionTypes
      responses:
        '200':
          description: The session type was restored successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/session-types/{sessionTypeId}/price-rules:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
    get:
      summary: List price rules for a session type
      tags:
        - SessionTypes
      operationId: listSessionTypePriceRules
      description: |
        Returns all `PriceRule`s configured for a `SessionType`, filterable
        by date range and weekday. Price rules let you charge different
        prices for the same session type at different times — peak vs
        off-peak, weekday vs weekend, seasonal overrides. The first rule
        whose conditions match the session occurrence wins.
      parameters:
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/weekdays'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSessionTypePriceRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a price rule for a session type
      tags:
        - SessionTypes
      operationId: createSessionTypePriceRule
      description: |
        Adds a new `PriceRule` to a `SessionType`. Filters (date range,
        time range, weekdays) combine to express common pricing scenarios.
        The first rule whose conditions match a given session occurrence
        determines the price; omitting all filters creates a fallback
        "always applies" rule.

        When `offering_standard_price` is enabled for the site, the session
        type's `standard_price` must be set before a price rule can be created. A
        zero amount counts as set. Requires the `SETTINGS_MANAGE` permission on
        the session type's site.
      requestBody:
        $ref: '#/components/requestBodies/CreateSessionTypePriceRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowSessionTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-types/{sessionTypeId}/price-rules/{priceRuleId}:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
      - $ref: '#/components/parameters/priceRuleId'
    get:
      summary: Retrieve a price rule
      tags:
        - SessionTypes
      operationId: getSessionTypePriceRule
      description: Returns a single `PriceRule` belonging to the given `SessionType`.
      responses:
        '200':
          $ref: '#/components/responses/ShowSessionTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a price rule
      tags:
        - SessionTypes
      operationId: updateSessionTypePriceRule
      description: |
        Partially updates a `PriceRule`. Every field is optional; omitted fields
        keep their current values. When `offering_standard_price` is enabled for
        the site, the session type's `standard_price` must be set before a price
        rule can be updated. A zero amount counts as set. Requires the
        `SETTINGS_MANAGE` permission on the session type's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateSessionTypePriceRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowSessionTypePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a price rule
      tags:
        - SessionTypes
      operationId: deleteSessionTypePriceRule
      description: |
        Removes a `PriceRule` from a `SessionType`. Past bookings already
        priced under this rule are unaffected — they retain the price set at
        booking time. Future sessions are repriced using whatever rules remain.
        When `offering_standard_price` is enabled for the site, the session
        type's `standard_price` must be set before a price rule can be deleted. A
        zero amount counts as set.
      responses:
        '204':
          description: Price rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-types/{sessionTypeId}/suggest-description:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
  /shop/session-types/{sessionTypeId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a SessionType
      description: Returns the localised `name`, `description`, `meta_title` and `meta_description` for the given locale.
      operationId: getSessionTypeLocaleStrings
      tags:
        - SessionTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowSessionTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a SessionType
      description: Sets the localised `name`, `description`, `meta_title` and/or `meta_description` for the given locale. Pass `null` to clear a translation and fall back to the default value.
      operationId: updateSessionTypeLocaleStrings
      tags:
        - SessionTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateSessionTypeLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateSessionTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/new-site-details/{newSiteDetailsId}:
    parameters:
      - $ref: '#/components/parameters/newSiteDetailsId'
  /shop/new-site-details/{newSiteDetailsId}/create-site:
    parameters:
      - $ref: '#/components/parameters/newSiteDetailsId'
  /shop/sites/{siteId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Retrieve a ShopSite
      description: Use this endpoint to retrieve a single `ShopSite`.
      operationId: getShopSite
      tags:
        - Sites
      responses:
        '200':
          description: The `ShopSite` was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetShopSite
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/ShopSite'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a ShopSite
      description: Use this endpoint to update a `ShopSite`.
      tags:
        - Sites
      operationId: updateShopSite
      requestBody:
        description: Updates the specified `Site` object by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateShopSite'
      responses:
        '200':
          description: The `ShopSite` was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateShopSiteResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/ShopSite'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/appointment-enquiry-settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Retrieve a site's appointment enquiry settings
      description: Use this endpoint to retrieve the appointment enquiry settings for a site
      tags:
        - Sites
      operationId: getAppointmentEnquirySettings
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentEnquirySettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a site's appointment enquiry settings
      description: Use this endpoint to update the appointment enquiry settings for a site
      tags:
        - Sites
      operationId: updateAppointmentEnquirySettings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAppointmentEnquirySettings'
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentEnquirySettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/check-email-from-address-verification:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/categories:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_voucherApplicable'
  /shop/sites/{siteId}/integrations/mews/rates:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/opening-hours-overrides:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Retrieve a ShopSites' opening hours overrides
      description: Use this endpoint to retrieve the overrides for a `ShopSite`s' opening hours.
      operationId: listShopSiteOpeningHoursOverrides
      tags:
        - Sites
      responses:
        '200':
          description: The `ShopSite`s' opening hours overrides were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListShopSiteOpeningHoursOverrides
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an opening hours override for a ShopSite
      description: Use this endpoint to create an exception for the `ShopSite`s' standard opening hours.
      operationId: createShopSiteOpeningHoursOverride
      tags:
        - Sites
      requestBody:
        $ref: '#/components/requestBodies/CreateShopSiteOpeningHoursOverride'
      responses:
        '201':
          description: An opening hours override was successfully created.
          content:
            application/json:
              schema:
                title: CreateShopSiteOpeningHoursOverrideResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/AvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/opening-hours-overrides/{openingHoursOverrideId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
      - $ref: '#/components/parameters/openingHoursOverrideId'
    get:
      summary: Retrieve a ShopSite opening hours override
      description: Use this endpoint to retrieve an override for a `ShopSite`s' opening hours.
      operationId: getShopSiteOpeningHoursOverride
      tags:
        - Sites
      responses:
        '200':
          description: The opening hour override was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetShopSiteOpeningHoursOverride
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/AvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a ShopSites' opening hour override
      description: |
        Update an existing override for a `ShopSite`s' opening hours. Use this
        endpoint when you need to amend a previously created exception — for
        example, extending a holiday closure by a day, or adjusting the time
        window during which the site is open. All fields in the request body
        are optional, but `date_from` and `date_to` together must form a valid
        range, and if `time_to` is provided it must fall after `time_from`.
      operationId: updateOpeningHoursOverride
      tags:
        - Sites
      requestBody:
        $ref: '#/components/requestBodies/UpdateShopSiteOpeningHoursOverride'
      responses:
        '200':
          description: The opening hour override was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateOpeningHoursOverride
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/AvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    patch:
      summary: Update a ShopSites' opening hour override
      description: Use this endpoint to update an override for a `ShopSite`s' opening hours.
      operationId: updateShopSiteOpeningHoursOverride
      tags:
        - Sites
      requestBody:
        $ref: '#/components/requestBodies/UpdateShopSiteOpeningHoursOverride'
      responses:
        '200':
          description: The opening hour override was successfully updated.
          content:
            application/json:
              schema:
                title: UpdateShopSiteOpeningHoursOverride
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/AvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a ShopSites' opening hours override
      description: Use this endpoint to delete an override for a `ShopSite`s' opening hours.
      operationId: deleteShopSiteOpeningHoursOverride
      tags:
        - Sites
      responses:
        '204':
          description: The opening hours override was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sites/{siteId}/revenue-centres:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
    get:
      summary: Get revenue centres for a site
      tags:
        - RevenueCentres
      operationId: getSiteRevenueCentres
      description: |
        Use this endpoint to retrieve a `Site`'s revenue centres.
      responses:
        '200':
          $ref: '#/components/responses/ListRevenueCentres'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a new revenue centre for the site
      tags:
        - RevenueCentres
      operationId: createSiteRevenueCentre
      description: |
        Use this endpoint to create a new revenue centre for a `Site`.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRevenueCentre'
      responses:
        '200':
          description: The revenue centre was successfully created
          $ref: '#/components/responses/ShowRevenueCentre'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/revenue-centres/{revenueCentreId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/revenueCentreId'
    get:
      summary: Get a revenue centre
      tags:
        - RevenueCentres
      operationId: getSiteRevenueCentre
      description: |
        Use this endpoint to retrieve a single revenue centre.
      responses:
        '200':
          $ref: '#/components/responses/ShowRevenueCentre'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a revenue centre
      tags:
        - RevenueCentres
      operationId: updateSiteRevenueCentre
      description: |
        Use this endpoint to update a revenue centre for a `Site`.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateRevenueCentre'
      responses:
        '200':
          description: The revenue centre was successfully created
          $ref: '#/components/responses/ShowRevenueCentre'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a revenue centre
      tags:
        - RevenueCentres
      operationId: deleteSiteRevenueCentre
      description: |
        Use this endpoint to delete a revenue centre from a `Site`.
      responses:
        '204':
          description: |
            The revenue centre was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sites/{siteId}/onboarding:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/onboarding/completed:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/onboarding/skip-step:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/onboarding/seen:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/suggest-opening-hours:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/integrations/adyen:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/adyen/sessions:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/belmond-bapi:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/cloudbeds:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/cloudbeds/house-accounts:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/cloudbeds/payment-methods:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/for-sight:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/for-sight/recent-attempts:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/for-sight/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/for-sight/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/for-sight/config:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/for-sight/settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/fiskaltrust:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/fiskaltrust/test-connection:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/fiskaly:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/fiskaly/test-connection:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/fiskaly/exports:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/fiskaly/exports/{exportId}/retrieve:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/exportId'
        required: true
  /shop/sites/{siteId}/integrations/gantner:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/giftpro:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/integrations/guestline/analysis-codes:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/integrations/guestline/payment-codes:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/integrations/guestline/pms-update-config:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/integrations/guestline/pms-update-config/rate-codes/{rateCode}:
    parameters:
      - $ref: '#/components/parameters/siteId'
      - $ref: '#/components/parameters/rateCode'
  /shop/sites/{siteId}/integrations/guestline/import-room-types:
    parameters:
      - $ref: '#/components/parameters/siteId'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/hconnect:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/maestro-pos:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/pacesetter:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/onq:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/onq/export-split-table:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/resdiary/{integrationConfigId}/booking-options:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId-2'
  /shop/sites/{siteId}/integrations/resdiary/{integrationConfigId}/restaurants:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId-2'
  /shop/sites/{siteId}/integrations/ohip:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/infor:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/infor/house-accounts:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/rezcontrol:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/rms:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/rms/properties:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/rms/sundries:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/rms/cards:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/rms/accounts:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/sevenrooms/{integrationConfigId}/venues:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId-2'
  /shop/sites/{siteId}/integrations/stayntouch:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/stayntouch/hotels:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/stayntouch/charge-codes:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/stayntouch/posting-accounts:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/tei:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/vips:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/reserve-with-google:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/pms-integrations:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/service-charge-settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Retrieve a site's service charge settings
      description: Use this endpoint to retrieve the service charge settings for a site
      tags:
        - Sites
      operationId: getServiceChargeSettings
      responses:
        '200':
          $ref: '#/components/responses/ShowServiceChargeSettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a site's service charge settings
      description: Use this endpoint to update the service charge settings for a site
      tags:
        - Sites
      operationId: updateServiceChargeSettings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateServiceChargeSettings'
      responses:
        '200':
          $ref: '#/components/responses/ShowServiceChargeSettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/auto-checkout-settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Retrieve a site's auto checkout settings
      description: Use this endpoint to retrieve auto checkout settings for a site
      tags:
        - Sites
      operationId: getAutoCheckoutSettings
      responses:
        '200':
          $ref: '#/components/responses/ShowAutoCheckoutSettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a site's auto checkout settings
      description: Use this endpoint to update the auto checkout settings for a site
      tags:
        - Sites
      operationId: updateAutoCheckoutSettings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAutoCheckoutSettings'
      responses:
        '200':
          $ref: '#/components/responses/ShowAutoCheckoutSettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/sms-settings:
    get:
      summary: Show SMS Notification Settings
      tags:
        - Sites
      operationId: getSmsNotificationSettings
      description: |
        This endpoint retrieves the SMS Notification Settings for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-26'
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsNotificationSettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update SMS Notification Settings
      tags:
        - Sites
      operationId: updateSmsNotificationSettings
      description: |
        This endpoint updates the SMS Notification Settings for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-26'
      requestBody:
        $ref: '#/components/requestBodies/UpdateSmsNotificationSettings'
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsNotificationSettings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/twilio-provisioning/{provisionId}/purchase:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-27'
      - $ref: '#/components/parameters/provisionId'
  /shop/sites/{siteId}/twilio-provisioning/{provisionId}/activate:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-27'
      - $ref: '#/components/parameters/provisionId'
  /shop/sites/{siteId}/twilio-provisioning/{provisionId}/retry:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-27'
      - $ref: '#/components/parameters/provisionId'
  /shop/sites/{siteId}/supported-comms-locales:
    get:
      summary: Get supported comms locales
      tags:
        - Sites
      operationId: getSupportedCommsLocales
      description: |
        This endpoint returns a list of the locales that are supported by the site.

        When a `Customer` has a preferred locale, if the locale is included in the site's supported comms locales,
        then any email communication will be sent in that preferred locale.

        The locales must be included in the platform's supported locales, which can be retrieved using the [`listMetaSupportedLocales`](/endpoints/Meta#listMetaSupportedLocales) endpoint.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-28'
      responses:
        '200':
          $ref: '#/components/responses/ListSupportedCommsLocales'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update supported comms locales
      tags:
        - Sites
      operationId: updateSupportedCommsLocales
      description: |
        This endpoint allows you to update the list of locales that are supported by the site.

        When a `Customer` has a preferred locale, if the locale is included in the site's supported comms locales,
        then any email communication will be sent in that preferred locale.

        The locales must be included in the platform's supported locales, which can be retrieved using the [`listMetaSupportedLocales`](/endpoints/Meta#listMetaSupportedLocales) endpoint.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-28'
      requestBody:
        $ref: '#/components/requestBodies/UpdateSupportedCommsLocales'
      responses:
        '200':
          $ref: '#/components/responses/ListSupportedCommsLocales'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/legal/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/siteId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve legal locale strings for a Site
      description: Returns the localised `terms` and `privacy_policy` for the given locale.
      operationId: getSiteLegalLocaleStrings
      tags:
        - Sites
      responses:
        '200':
          $ref: '#/components/responses/ShowSiteLegalLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update legal locale strings for a Site
      description: Sets the localised `terms` and/or `privacy_policy` for the given locale. Pass `null` to clear the translation and fall back to the default content.
      operationId: updateSiteLegalLocaleStrings
      tags:
        - Sites
      requestBody:
        $ref: '#/components/requestBodies/UpdateSiteLegalLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateSiteLegalLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/locations:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/features:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
    get:
      summary: Get the features of a Site
      tags:
        - Sites
      operationId: getSiteFeatures
      description: |
        Use this endpoint to retrieve the features of an existing `Site`.
      responses:
        '200':
          $ref: '#/components/responses/ShowSiteFeatures'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update the features of a Site
      tags:
        - Sites
      operationId: updateSiteFeatures
      description: |
        Use this endpoint to update the features of an existing `Site`.
      requestBody:
        $ref: '#/components/requestBodies/UpdateSiteFeatures'
      responses:
        '200':
          $ref: '#/components/responses/ShowSiteFeatures'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/shop-config:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/shop-config/offering-order:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Get details of all offerings available on the shop in their specified order
      tags:
        - Sites
      operationId: getOfferingOrder
      description: |
        This endpoint retrieves the details of all offerings available on the shop in their specified order for the given site.
      responses:
        '200':
          $ref: '#/components/responses/ShowOfferingOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update the order of offerings available on the shop
      tags:
        - Sites
      operationId: updateOfferingOrder
      description: |
        Use this endpoint to update the order of offerings available on the shop for a specific site.
      requestBody:
        $ref: '#/components/requestBodies/OrderedOfferings'
      responses:
        '200':
          $ref: '#/components/responses/ShowOfferingOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/shop-config/sso:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Get the SSO configuration for a site
      tags:
        - Sites
      operationId: getSsoConfig
      description: |
        This endpoint retrieves the SSO configuration for a specific site.
      responses:
        '200':
          $ref: '#/components/responses/ShowSsoConfig'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update the SSO configuration for a site
      tags:
        - Sites
      operationId: updateSsoConfig
      description: |
        Use this endpoint to update the SSO configuration for a specific site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateSsoConfig'
      responses:
        '200':
          $ref: '#/components/responses/ShowSsoConfig'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/shop-config/sso/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/shop-config/sso/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /shop/sites/{siteId}/billing-portal:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/billing-setup:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/billing-setup-complete:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_sessionId'
      - $ref: '#/components/parameters/signature'
  /shop/sites/{siteId}/custom-payment-types:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
    get:
      summary: List a Site's custom payment types
      tags:
        - Sites
      operationId: listSiteCustomPaymentTypes
      description: |
        Returns the set of `CustomPaymentType`s enabled for the given
        `Site`. Custom payment types let operators record tenders that
        are not handled by the platform's first-class processors —
        typical examples include third-party voucher providers, hotel
        PMS prepayments, and arbitrary "cash equivalent" tenders.

        Custom payment types are defined at the organisation level via
        the `/shop/organisations/{organisationId}/custom-payment-types`
        endpoints; this endpoint returns the subset associated with the
        named `Site`.
      responses:
        '200':
          description: The `Site`'s custom payment types were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListSiteCustomPaymentTypes
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CustomPaymentType'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sites/{siteId}/preview-email-branding:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/logoMediaId'
      - $ref: '#/components/parameters/accentColour'
      - $ref: '#/components/parameters/backgroundColour'
      - $ref: '#/components/parameters/textColour'
      - $ref: '#/components/parameters/successColour'
      - $ref: '#/components/parameters/successContrastColour'
      - $ref: '#/components/parameters/infoColour'
      - $ref: '#/components/parameters/infoContrastColour'
      - $ref: '#/components/parameters/dangerColour'
      - $ref: '#/components/parameters/dangerContrastColour'
      - $ref: '#/components/parameters/greetingType'
      - $ref: '#/components/parameters/signOffType'
      - $ref: '#/components/parameters/basketConfirmedEmailMessage'
  /shop/sites/{siteId}/sold-by-users:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
    get:
      summary: List sold-by users for a Site
      tags:
        - Sites
      operationId: listSiteSoldByUsers
      description: |
        Returns the combined list of Trybe users and `Practitioner`s who
        can be selected as the "sold by" attribution on an `Order`,
        `OrderLine`, or basket. The list is filtered to those that belong
        to the named `Site`'s organisation.

        Use the returned `id` and `type` values to populate `sold_by`
        fields when creating or updating sales records.
      responses:
        '200':
          description: The sold-by entities were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListSiteSoldByUsers
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SoldByUser'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/kiosk/kiosk-config/{kioskConfigId}:
    parameters:
      - $ref: '#/components/parameters/kioskConfigId'
  /shop/kiosk/kiosk-devices/{kioskDeviceId}:
    parameters:
      - $ref: '#/components/parameters/kioskDeviceId'
  /shop/kiosk/kiosk-buffer-times/{kioskBufferTimeRuleId}:
    parameters:
      - $ref: '#/components/parameters/kioskBufferTimeRuleId'
  /shop/kiosk/kiosk-instructions/{kioskInstructionId}:
    parameters:
      - $ref: '#/components/parameters/kioskInstructionId'
  /shop/kiosk/kiosk-instructions/{kioskInstructionId}/restore:
    parameters:
      - $ref: '#/components/parameters/kioskInstructionId'
  /shop/message-fragments:
    get:
      summary: List message fragments
      tags:
        - MessageFragments
      operationId: listMessageFragments
      description: |
        Retrieves the message fragments configured for the given site.
        Without `offering_id`, results are sorted alphabetically by
        `name`. When `offering_id` is supplied, results are filtered to
        fragments that apply to that offering and sorted by
        `message_type` then ascending `priority` - the order they will
        be rendered into the customer email.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-29'
        - $ref: '#/components/parameters/offering_id'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListMessageFragments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a message fragment
      tags:
        - MessageFragments
      operationId: createMessageFragment
      description: |
        Creates a new message fragment at the given site. The fragment
        is immediately eligible to be rendered into outgoing emails of
        the matching `message_type` once any `offerings` or
        `permitted_membership_type_ids` filters are satisfied. Requires
        the `SETTINGS_MANAGE` permission.
      requestBody:
        $ref: '#/components/requestBodies/CreateMessageFragment'
      responses:
        '201':
          $ref: '#/components/responses/ShowMessageFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/message-fragments/{messageFragmentId}:
    parameters:
      - $ref: '#/components/parameters/messageFragmentId'
    get:
      summary: Show a message fragment
      description: Retrieves a single message fragment by ID.
      tags:
        - MessageFragments
      operationId: getMessageFragment
      responses:
        '200':
          $ref: '#/components/responses/ShowMessageFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a message fragment
      description: |
        Updates an existing message fragment. Omitting
        `permitted_membership_type_ids` (or sending an empty array)
        clears the membership filter so the fragment becomes available
        to all customers; supply the field with the desired IDs to keep
        or change the restriction. Requires the `SETTINGS_MANAGE`
        permission on the fragment's site.
      tags:
        - MessageFragments
      operationId: updateMessageFragment
      requestBody:
        $ref: '#/components/requestBodies/UpdateMessageFragment'
      responses:
        '200':
          $ref: '#/components/responses/ShowMessageFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a message fragment
      description: |
        Soft-deletes a message fragment. Once archived the fragment is
        no longer included in outgoing emails, but its history is
        retained for auditing.
      tags:
        - MessageFragments
      operationId: deleteMessageFragment
      responses:
        '204':
          description: The message fragment was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/message-fragments/{messageFragmentId}/copy:
    parameters:
      - $ref: '#/components/parameters/messageFragmentId'
    post:
      summary: Duplicate a message fragment
      description: |
        Creates a copy of an existing `MessageFragment`, applying any
        overrides supplied in the request body. Useful when seeding
        similar email copy (e.g. per-offering variants of a shared
        template, or A/B test variants).

        Requires the `SETTINGS_MANAGE` permission on the source
        fragment's site, plus the `create` ability on `MessageFragment`.
        The copy is created at the source fragment's site.
      operationId: copyMessageFragment
      tags:
        - MessageFragments
      requestBody:
        $ref: '#/components/requestBodies/CopyMessageFragment'
      responses:
        '201':
          $ref: '#/components/responses/ShowMessageFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/message-fragments/{messageFragmentId}/offerings:
    parameters:
      - $ref: '#/components/parameters/messageFragmentId'
    post:
      summary: Attach an offering to a message fragment
      description: |
        Adds an offering to the fragment's `offerings` list. Once
        attached, the fragment will be rendered into emails whose
        booking contains the offering (subject to `message_type` and
        `permitted_membership_type_ids` filters). Adding an offering
        that is already attached is a no-op.

        Requires the `update` ability on the target fragment, which is
        granted via the `SETTINGS_MANAGE` permission on the fragment's
        site.
      operationId: createMessageFragmentOffering
      tags:
        - MessageFragments
      requestBody:
        $ref: '#/components/requestBodies/AddMessageFragmentOffering'
      responses:
        '200':
          $ref: '#/components/responses/ShowMessageFragment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/message-fragments/{messageFragmentId}/offerings/{offeringId}:
    parameters:
      - $ref: '#/components/parameters/messageFragmentId'
      - $ref: '#/components/parameters/parameters_offeringId-4'
    delete:
      summary: Detach an offering from a message fragment
      description: |
        Removes an offering from the fragment's `offerings` list. After
        removal the fragment will no longer be selected for emails whose
        booking only contains the detached offering. If the resulting
        `offerings` list is empty the fragment reverts to applying to
        every offering at the site (the global fallback behaviour).

        Removing an offering that is not attached is a no-op. Requires
        the `update` ability on the target fragment.
      operationId: deleteMessageFragmentOffering
      tags:
        - MessageFragments
      responses:
        '200':
          $ref: '#/components/responses/ShowMessageFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/message-fragments/{messageFragmentId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/messageFragmentId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a MessageFragment
      description: Returns the localised `name` and `message` for the given locale.
      operationId: getMessageFragmentLocaleStrings
      tags:
        - MessageFragments
      responses:
        '200':
          $ref: '#/components/responses/ShowMessageFragmentLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a MessageFragment
      description: Sets the localised `name` and/or `message` for the given locale.
      operationId: updateMessageFragmentLocaleStrings
      tags:
        - MessageFragments
      requestBody:
        $ref: '#/components/requestBodies/UpdateMessageFragmentLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateMessageFragmentLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sms-fragments:
    get:
      summary: List SMS Message Fragments
      tags:
        - SmsFragments
      operationId: listSmsFragments
      description: |
        This endpoint retrieves a list of all the SMS Message Fragments for the given site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-30'
        - $ref: '#/components/parameters/parameters_offering_id'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSmsFragments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create an SMS Message Fragment
      tags:
        - SmsFragments
      operationId: createSmsFragment
      description: |
        This endpoint creates an SMS Message Fragment for the given site.
      requestBody:
        $ref: '#/components/requestBodies/CreateSmsFragment'
      responses:
        '201':
          $ref: '#/components/responses/ShowSmsFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sms-fragments/{smsFragmentId}:
    parameters:
      - $ref: '#/components/parameters/smsFragmentId'
    get:
      summary: Show an SMS Message Fragment
      description: |
        This endpoint retrieves an SMS Message Fragment by ID.
      tags:
        - SmsFragments
      operationId: getSmsFragment
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an SMS Message Fragment
      description: |
        This endpoint updates an SMS Message Fragment by ID.
      tags:
        - SmsFragments
      operationId: updateSmsFragment
      requestBody:
        $ref: '#/components/requestBodies/UpdateSmsFragment'
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive an SMS Message Fragment
      description: |
        This endpoint soft deletes an SMS Message Fragment by ID.
      tags:
        - SmsFragments
      operationId: deleteSmsFragment
      responses:
        '204':
          description: The SMS Message Fragment was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sms-fragments/{smsFragmentId}/copy:
    parameters:
      - $ref: '#/components/parameters/smsFragmentId'
    post:
      summary: Duplicate an SMS fragment
      description: |
        Creates a copy of an existing `SmsFragment` with new fields applied
        from the request body. Useful when seeding similar messaging
        content (e.g. variants for A/B testing, or per-offering overrides
        of a shared template).

        Requires the `SETTINGS_MANAGE` permission on the source fragment's
        site, plus the `create` permission on `SmsFragment`. The copy is
        created at the source's site.
      operationId: copySmsFragment
      tags:
        - SmsFragments
      requestBody:
        $ref: '#/components/requestBodies/CopySmsFragment'
      responses:
        '201':
          $ref: '#/components/responses/ShowSmsFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sms-fragments/{smsFragmentId}/restore:
    parameters:
      - $ref: '#/components/parameters/smsFragmentId'
    post:
      summary: Restore an SMS Message Fragment
      description: |
        This endpoint restores an archived (soft-deleted) SMS Message Fragment by ID.
      tags:
        - SmsFragments
      operationId: restoreSmsFragment
      responses:
        '200':
          $ref: '#/components/responses/ShowSmsFragment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/reports/appointment-enquiries:
    get:
      summary: List appointment enquiries
      operationId: listAppointmentEnquiries
      tags:
        - AppointmentEnquiries
      description: |
        Use this endpoint to retrieve a list of `AppointmentEnquiry` resources associated with a `Site`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-31'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_status-6'
        - $ref: '#/components/parameters/canConfirm'
        - $ref: '#/components/parameters/receivedFrom'
        - $ref: '#/components/parameters/receivedTo'
        - $ref: '#/components/parameters/parameters_appointmentTypeId-2'
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/parameters_sortOrder'
      responses:
        '200':
          description: The list of `AppointmentEnquiry` resources was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListAppointmentEnquiriesResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/appointment-enquiries/queue:
    get:
      summary: Queue an export of the appointment enquiries list
      tags:
        - AppointmentEnquiries
      operationId: actionQueueAppointmentEnquirieReport
      description: This endpoint queues an export of the appointment enquiries list.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-31'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_status-6'
        - $ref: '#/components/parameters/canConfirm'
        - $ref: '#/components/parameters/receivedFrom'
        - $ref: '#/components/parameters/receivedTo'
        - $ref: '#/components/parameters/parameters_appointmentTypeId-2'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/appointment-enquiries/smart-filters:
    get:
      summary: Get a list of smart filters for the appointment enquiries list.
      tags:
        - AppointmentEnquiries
      operationId: getAppointmentEnquiriesSmartFilters
      description: This endpoint retrieves a list of smart filters for the appointment enquiries list.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-31'
      responses:
        '200':
          description: The smart filters were retrieved
          $ref: '#/components/responses/SmartFiltersResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/client-associated-barcodes:
    get:
      summary: List ClientAssociatedBarcodes
      operationId: listClientAssociatedBarcodes
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a list of `ClientAssociatedBarcode` resources for reporting purposes.
        This endpoint supports filtering by various criteria including created date, expiry date, order, customer, source, and payment method.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-32'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_createdAtFrom'
        - $ref: '#/components/parameters/parameters_createdAtTo'
        - $ref: '#/components/parameters/expiresAtFrom'
        - $ref: '#/components/parameters/expiresAtTo'
        - $ref: '#/components/parameters/hasOrder'
        - $ref: '#/components/parameters/hasPaymentMethod'
        - $ref: '#/components/parameters/parameters_source'
      responses:
        '200':
          description: The list of `ClientAssociatedBarcode` resources was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListClientAssociatedBarcodesResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/client-associated-barcodes/queue:
    get:
      summary: Queue an export of the client associated barcodes report
      tags:
        - Reports
      operationId: actionQueueClientAssociatedBarcodesReport
      description: This endpoint queues an export of the client associated barcodes report. The report will be generated asynchronously and delivered via the configured delivery method.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-32'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_createdAtFrom'
        - $ref: '#/components/parameters/parameters_createdAtTo'
        - $ref: '#/components/parameters/expiresAtFrom'
        - $ref: '#/components/parameters/expiresAtTo'
        - $ref: '#/components/parameters/hasOrder'
        - $ref: '#/components/parameters/hasPaymentMethod'
        - $ref: '#/components/parameters/parameters_source'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/itinerary:
    parameters:
      - $ref: '#/components/parameters/parameters_date-5'
      - $ref: '#/components/parameters/parameters_siteId-33'
    get:
      summary: Date Itinerary Report Queue
      description: |
        This endpoint queues an export of a full day's itinerary for a given date.
      operationId: getDateItineraryQueue
      tags:
        - Reports
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/ledger-lines:
    get:
      summary: List LedgerLines
      operationId: listLedgerLines
      tags:
        - LedgerLines
      description: |
        Use this endpoint to retrieve a list of `LedgerLine` resources associated with a `Site`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-34'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/ledgerDateFrom'
        - $ref: '#/components/parameters/ledgerDateTo'
        - $ref: '#/components/parameters/parameters_type-2'
        - $ref: '#/components/parameters/revenueCentre'
        - $ref: '#/components/parameters/paymentProcessor'
        - $ref: '#/components/parameters/paymentProcessorTypeId'
        - $ref: '#/components/parameters/parameters_voucherCodeId-2'
      responses:
        '200':
          description: The list of `LedgerLines` resources was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListLedgerLinesResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/ledger-lines/queue:
    get:
      summary: Queue an export of the ledger lines report
      tags:
        - LedgerLines
      operationId: actionQueueLedgerLineReport
      description: This endpoint queues an export of the ledger lines list report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-34'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/ledgerDateFrom'
        - $ref: '#/components/parameters/ledgerDateTo'
        - $ref: '#/components/parameters/parameters_type-2'
        - $ref: '#/components/parameters/revenueCentre'
        - $ref: '#/components/parameters/paymentProcessor'
        - $ref: '#/components/parameters/paymentProcessorTypeId'
        - $ref: '#/components/parameters/parameters_voucherCodeId-2'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/payouts:
    get:
      summary: List payouts for a site
      operationId: listPayouts
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a list of payouts for a site.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-35'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_status-7'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          description: The list of `Payout` resources was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListPayoutsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/payouts/{payoutId}:
    parameters:
      - $ref: '#/components/parameters/payoutId'
  /shop/reports/practitioner-occupancy:
    get:
      operationId: getPractitionerOccupancyReport
      summary: Get practitioner occupancy report
      description: |
        Returns a practitioner occupancy report for the given date/time range, showing bookable, blocked, appointment and session minutes per practitioner. The date range must not exceed 60 days. Requires the `REPORTS_VIEW` permission. When requesting a CSV export via the `Accept: text/csv` header, requires the `REPORTS_DOWNLOAD` permission instead.
      tags:
        - Reports
      parameters:
        - $ref: '#/components/parameters/PractitionerOccupancyDateTimeFrom'
        - $ref: '#/components/parameters/PractitionerOccupancyDateTimeTo'
        - $ref: '#/components/parameters/PractitionerOccupancyPractitionerIds'
        - $ref: '#/components/parameters/PractitionerOccupancySiteId'
      responses:
        '200':
          $ref: '#/components/responses/PractitionerOccupancyReportResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/reports/practitioner-occupancy/queue:
    get:
      operationId: queuePractitionerOccupancyReport
      summary: Queue practitioner occupancy report export
      description: |
        Queues a practitioner occupancy report for asynchronous CSV export. Returns a queued job resource that can be polled for completion. Requires the `REPORTS_DOWNLOAD` permission.
      tags:
        - Reports
      parameters:
        - $ref: '#/components/parameters/PractitionerOccupancyDateTimeFrom'
        - $ref: '#/components/parameters/PractitionerOccupancyDateTimeTo'
        - $ref: '#/components/parameters/PractitionerOccupancyPractitionerIds'
        - $ref: '#/components/parameters/PractitionerOccupancySiteId'
      responses:
        '200':
          $ref: '#/components/responses/PractitionerOccupancyQueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/reports/practitioner-occupancy-by-date:
    get:
      operationId: getPractitionerOccupancyByDateReport
      summary: Get practitioner occupancy report by date
      description: |
        Returns a practitioner occupancy report for the given date/time range, showing bookable, blocked, appointment and session minutes per practitioner per day. The date range must not exceed 60 days. Requires the `REPORTS_VIEW` permission. When requesting a CSV export via the `Accept: text/csv` header, requires the `REPORTS_DOWNLOAD` permission instead.
      tags:
        - Reports
      parameters:
        - $ref: '#/components/parameters/PractitionerOccupancyByDateDateTimeFrom'
        - $ref: '#/components/parameters/PractitionerOccupancyByDateDateTimeTo'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/PractitionerOccupancyByDatePractitionerIds'
        - $ref: '#/components/parameters/PractitionerOccupancyByDateSiteId'
        - $ref: '#/components/parameters/PractitionerOccupancyByDateZoneId'
      responses:
        '200':
          $ref: '#/components/responses/PractitionerOccupancyByDateReportResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/reports/practitioner-occupancy-by-date/queue:
    get:
      operationId: queuePractitionerOccupancyByDateReport
      summary: Queue practitioner occupancy by date report export
      description: |
        Queues a practitioner occupancy by date report for asynchronous CSV export. Returns a queued job resource that can be polled for completion. Requires the `REPORTS_DOWNLOAD` permission.
      tags:
        - Reports
      parameters:
        - $ref: '#/components/parameters/PractitionerOccupancyByDateDateTimeFrom'
        - $ref: '#/components/parameters/PractitionerOccupancyByDateDateTimeTo'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/PractitionerOccupancyByDatePractitionerIds'
        - $ref: '#/components/parameters/PractitionerOccupancyByDateSiteId'
        - $ref: '#/components/parameters/PractitionerOccupancyByDateZoneId'
      responses:
        '200':
          $ref: '#/components/responses/PractitionerOccupancyByDateQueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/reports/promo-code-usage/summary:
    get:
      summary: Promo code usage summary
      tags:
        - DiscountUsage
      operationId: listUsedPromoCodesSummary
      description: |
        This endpoint summarises the total discount usage by promo code across all orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-36'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-3'
        - $ref: '#/components/parameters/parameters_revenueDateTo-3'
        - $ref: '#/components/parameters/parameters_submittedAtFrom'
        - $ref: '#/components/parameters/parameters_submittedAtTo'
      responses:
        '200':
          $ref: '#/components/responses/ListUsedPromoCodesSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/promo-code-usage/summary/queue:
    get:
      summary: Promo code usage summary queue
      tags:
        - DiscountUsage
      operationId: getUsedPromoCodesSummaryQueue
      description: |
        This endpoint queues an export of the summary of the total discount usage by promo code across all orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-36'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-3'
        - $ref: '#/components/parameters/parameters_revenueDateTo-3'
        - $ref: '#/components/parameters/parameters_submittedAtFrom'
        - $ref: '#/components/parameters/parameters_submittedAtTo'
      responses:
        '200':
          description: The request to queue the summary of `UsedPromoCodes` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/promo-code-usage/breakdown:
    get:
      summary: Promo code usage breakdown
      tags:
        - DiscountUsage
      operationId: listUsedPromoCodesBreakdown
      description: |
        This endpoint provides a breakdown of discount usage by promo code for individual orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-37'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-4'
        - $ref: '#/components/parameters/parameters_revenueDateTo-4'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-2'
        - $ref: '#/components/parameters/parameters_submittedAtTo-2'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/parameters_sortOrder'
        - $ref: '#/components/parameters/appliedBy'
      responses:
        '200':
          $ref: '#/components/responses/ListUsedPromoCodesBreakdown'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/promo-code-usage/breakdown/queue:
    get:
      summary: Promo code usage breakdown queue
      tags:
        - DiscountUsage
      operationId: getUsedPromoCodesBreakdownQueue
      description: |
        This endpoint queues an export of the breakdown of discount usage by promo code for individual orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-37'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-4'
        - $ref: '#/components/parameters/parameters_revenueDateTo-4'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-2'
        - $ref: '#/components/parameters/parameters_submittedAtTo-2'
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/parameters_sortOrder'
        - $ref: '#/components/parameters/appliedBy'
      responses:
        '200':
          description: The request to queue the breakdown of `UsedPromoCodes` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/discount-type-usage/summary:
    get:
      summary: Discount type usage summary
      tags:
        - DiscountUsage
      operationId: listUsedDiscountTypesSummary
      description: |
        This endpoint summarises the total discount usage by discount type across all orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-38'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-5'
        - $ref: '#/components/parameters/parameters_revenueDateTo-5'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-3'
        - $ref: '#/components/parameters/parameters_submittedAtTo-3'
        - $ref: '#/components/parameters/parameters_discountType'
        - $ref: '#/components/parameters/discountAppliedFrom'
        - $ref: '#/components/parameters/discountAppliedTo'
      responses:
        '200':
          $ref: '#/components/responses/ListUsedDiscountTypesSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/discount-type-usage/summary/queue:
    get:
      summary: Discount type usage summary queue
      tags:
        - DiscountUsage
      operationId: getUsedDiscountTypesSummaryQueue
      description: |
        This endpoint queues an export of the summary of the total discount usage by discount type across all orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-38'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-5'
        - $ref: '#/components/parameters/parameters_revenueDateTo-5'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-3'
        - $ref: '#/components/parameters/parameters_submittedAtTo-3'
        - $ref: '#/components/parameters/parameters_discountType'
        - $ref: '#/components/parameters/discountAppliedFrom'
        - $ref: '#/components/parameters/discountAppliedTo'
      responses:
        '200':
          description: The request to queue the summary of `UsedDiscountTypes` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/discount-type-usage/breakdown:
    get:
      summary: Discount type usage breakdown
      tags:
        - DiscountUsage
      operationId: listUsedDiscountTypesBreakdown
      description: |
        This endpoint provides a breakdown of discount usage by discount type for individual orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-39'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-6'
        - $ref: '#/components/parameters/parameters_revenueDateTo-6'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-4'
        - $ref: '#/components/parameters/parameters_submittedAtTo-4'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/parameters_sortOrder'
        - $ref: '#/components/parameters/parameters_appliedBy'
        - $ref: '#/components/parameters/parameters_discountType-2'
        - $ref: '#/components/parameters/discountAppliedFrom'
        - $ref: '#/components/parameters/discountAppliedTo'
      responses:
        '200':
          $ref: '#/components/responses/ListUsedDiscountTypesBreakdown'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/discount-type-usage/breakdown/queue:
    get:
      summary: Discount type usage breakdown queue
      tags:
        - DiscountUsage
      operationId: getUsedDiscountTypesBreakdownQueue
      description: |
        This endpoint queues an export of the breakdown of discount usage by discount type for individual orders matching the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-39'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-6'
        - $ref: '#/components/parameters/parameters_revenueDateTo-6'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-4'
        - $ref: '#/components/parameters/parameters_submittedAtTo-4'
        - $ref: '#/components/parameters/parameters_appliedBy'
        - $ref: '#/components/parameters/parameters_discountType-2'
        - $ref: '#/components/parameters/discountAppliedFrom'
        - $ref: '#/components/parameters/discountAppliedTo'
      responses:
        '200':
          description: The request to queue the breakdown of `UsedDiscountTypes` was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/deposit-ledger-v2/list:
    get:
      summary: List LedgerLines
      operationId: listDepositLedger
      tags:
        - DepositLedger
      description: |
        Use this endpoint to retrieve a list of `DepositLedgerDailyChange` resources.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-40'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_date-6'
      responses:
        '200':
          description: The list of `DepositLedgerDailyChange` resources was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListDepositLedgerResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/deposit-ledger-v2/summary:
    get:
      summary: Get deposit ledger balances as of the given date
      operationId: getDepositLedgerSummary
      tags:
        - DepositLedger
      description: Get deposit ledger balances as of the given date.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-40'
        - $ref: '#/components/parameters/parameters_date-6'
      responses:
        '200':
          description: A summary of the deposit ledger balances on the given date.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepositLedgerSummaryResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/deposit-ledger-v2/queue:
    get:
      summary: Queue an export of the deposit ledger.
      description: Queue an export of the deposit ledger.
      tags:
        - DepositLedger
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-40'
        - $ref: '#/components/parameters/parameters_date-6'
      operationId: actionQueueDepositLedgerReport
      responses:
        '200':
          description: The request to queue the job was successful.
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/voucher-ledger/list:
    get:
      summary: List LedgerLines
      operationId: listVoucherLedger
      tags:
        - VoucherLedger
      description: |
        Use this endpoint to retrieve a list of `VoucherLedgerVoucher` resources.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-41'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_date-7'
      responses:
        '200':
          description: The list of `VoucherLedgerVoucher` resources was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListVoucherLedgerResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/voucher-ledger/summary:
    get:
      summary: Get voucher ledger balances as of the given date
      operationId: getVoucherLedgerSummary
      tags:
        - VoucherLedger
      description: Get voucher ledger balances as of the given date.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-41'
        - $ref: '#/components/parameters/parameters_date-7'
      responses:
        '200':
          description: A summary of the voucher ledger balances on the given date.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VoucherLedgerSummaryResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/voucher-ledger/queue:
    get:
      summary: Queue an export of the voucher ledger.
      description: Queue an export of the voucher ledger.
      tags:
        - VoucherLedger
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-41'
        - $ref: '#/components/parameters/parameters_date-7'
      operationId: actionQueueVoucherLedgerReport
      responses:
        '200':
          description: The request to queue the job was successful.
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/service-charge-items:
    get:
      summary: List service charge items
      operationId: listServiceChargeItems
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a paginated list of basket items with their service charge amounts.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-42'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_offeringType-3'
        - $ref: '#/components/parameters/parameters_offeringId-5'
        - $ref: '#/components/parameters/parameters_offeringCategory'
        - $ref: '#/components/parameters/parameters_soldById'
        - $ref: '#/components/parameters/parameters_orderStatus'
        - $ref: '#/components/parameters/parameters_status-8'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-7'
        - $ref: '#/components/parameters/parameters_revenueDateTo-7'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtFrom-2'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtTo-2'
        - $ref: '#/components/parameters/parameters_orderLabel'
        - $ref: '#/components/parameters/parameters_itemDateFrom-2'
        - $ref: '#/components/parameters/parameters_itemDateTo-2'
        - $ref: '#/components/parameters/parameters_practitionerId-6'
        - $ref: '#/components/parameters/parameters_roomId-4'
        - $ref: '#/components/parameters/parameters_zoneId-5'
      responses:
        '200':
          description: The list of items was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListServiceChargeItemsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/service-charge-items/queue:
    get:
      summary: Queue an export of the service charge items report
      tags:
        - Reports
      operationId: actionQueueServiceChargeItemsReport
      description: This endpoint queues an export of the service charge items report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-42'
        - $ref: '#/components/parameters/parameters_offeringType-3'
        - $ref: '#/components/parameters/parameters_offeringId-5'
        - $ref: '#/components/parameters/parameters_offeringCategory'
        - $ref: '#/components/parameters/parameters_soldById'
        - $ref: '#/components/parameters/parameters_orderStatus'
        - $ref: '#/components/parameters/parameters_status-8'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-7'
        - $ref: '#/components/parameters/parameters_revenueDateTo-7'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtFrom-2'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtTo-2'
        - $ref: '#/components/parameters/parameters_orderLabel'
        - $ref: '#/components/parameters/parameters_itemDateFrom-2'
        - $ref: '#/components/parameters/parameters_itemDateTo-2'
        - $ref: '#/components/parameters/parameters_practitionerId-6'
        - $ref: '#/components/parameters/parameters_roomId-4'
        - $ref: '#/components/parameters/parameters_zoneId-5'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/tips:
    get:
      summary: List tip items
      operationId: listTipItems
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a paginated list of items that have tip amounts associated with them.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-43'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-8'
        - $ref: '#/components/parameters/parameters_revenueDateTo-8'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-5'
        - $ref: '#/components/parameters/parameters_submittedAtTo-5'
      responses:
        '200':
          description: The list of items was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListTipItemsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/tips/queue:
    get:
      summary: Queue an export of the tip report
      tags:
        - Reports
      operationId: actionQueueTipReport
      description: This endpoint queues an export of the tip report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-43'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-8'
        - $ref: '#/components/parameters/parameters_revenueDateTo-8'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-5'
        - $ref: '#/components/parameters/parameters_submittedAtTo-5'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/sessions:
    get:
      summary: List appointment enquiries
      operationId: listReportSessions
      tags:
        - Reports
      description: Use this endpoint to retrieve a list of `Session`s.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-44'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_id-2'
        - $ref: '#/components/parameters/parameters_date-8'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_startTimeFrom'
        - $ref: '#/components/parameters/parameters_startTimeTo'
        - $ref: '#/components/parameters/parameters_sessionTypeId-3'
        - $ref: '#/components/parameters/parameters_recurrenceGroupId-2'
        - $ref: '#/components/parameters/parameters_roomId-5'
        - $ref: '#/components/parameters/parameters_practitionerId-7'
        - $ref: '#/components/parameters/parameters_zoneId-6'
        - $ref: '#/components/parameters/parameters_includeCancelled'
        - $ref: '#/components/parameters/parameters_cancelled'
        - $ref: '#/components/parameters/parameters_includeBookings-2'
      responses:
        '200':
          description: The list of `Session` resources was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListSessionsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/sessions/queue:
    get:
      summary: Queue an export of the sessions list
      tags:
        - Reports
      operationId: actionQueueSessionListReport
      description: This endpoint queues an export of the sessions list.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-44'
        - $ref: '#/components/parameters/parameters_date-8'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_startTimeFrom'
        - $ref: '#/components/parameters/parameters_startTimeTo'
        - $ref: '#/components/parameters/parameters_sessionTypeId-3'
        - $ref: '#/components/parameters/parameters_recurrenceGroupId-2'
        - $ref: '#/components/parameters/parameters_roomId-5'
        - $ref: '#/components/parameters/parameters_practitionerId-7'
        - $ref: '#/components/parameters/parameters_zoneId-6'
        - $ref: '#/components/parameters/parameters_includeCancelled'
        - $ref: '#/components/parameters/parameters_cancelled'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-centre-v2:
    get:
      summary: Revenue by centre report
      tags:
        - RevenueByCentre
      operationId: listRevenueByCentreSummary
      description: |
        This endpoint provides a summary of revenue by reporting centre for the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-45'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-9'
        - $ref: '#/components/parameters/parameters_revenueDateTo-9'
        - $ref: '#/components/parameters/parameters_labels'
      responses:
        '200':
          $ref: '#/components/responses/ListRevenueByCentreSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/revenue-by-centre-v2/queue:
    get:
      summary: Revenue by centre summary queue
      tags:
        - RevenueByCentre
      operationId: getRevenueByCentreSummaryQueue
      description: |
        This endpoint queues an export of the summary of revenue by reporting centre for the given parameters.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-45'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-9'
        - $ref: '#/components/parameters/parameters_revenueDateTo-9'
        - $ref: '#/components/parameters/parameters_labels'
      responses:
        '200':
          description: The request to queue the summary of revenue by reporting centre was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/revenue-by-centre:
    get:
      summary: Organisation revenue by centre report
      tags:
        - OrganisationReports
      operationId: getOrganisationRevenueByCentreReport
      description: Get a report of revenue by centre for all sites in an organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_revenueDateFrom-10'
        - $ref: '#/components/parameters/parameters_revenueDateTo-10'
        - $ref: '#/components/parameters/parameters_itemDateFrom-3'
        - $ref: '#/components/parameters/parameters_itemDateTo-3'
        - $ref: '#/components/parameters/parameters_labels-2'
        - $ref: '#/components/parameters/parameters_siteId-46'
      responses:
        '200':
          $ref: '#/components/responses/OrganisationRevenueByCentreResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/revenue-by-centre/queue:
    get:
      summary: Queue an export of the organisation revenue by centre report.
      tags:
        - OrganisationReports
      operationId: actionQueueOrganisationRevenueByCentreReport
      description: |
        This endpoint queues an export of the organisation revenue by centre report.
      parameters:
        - $ref: '#/components/parameters/parameters_revenueDateFrom-10'
        - $ref: '#/components/parameters/parameters_revenueDateTo-10'
        - $ref: '#/components/parameters/parameters_itemDateFrom-3'
        - $ref: '#/components/parameters/parameters_itemDateTo-3'
      responses:
        '200':
          description: The request to queue the report was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/authentication-log:
    get:
      summary: Organisation Authentication log report
      tags:
        - OrganisationReports
      operationId: getAuthenticationLogReport
      description: |
        This endpoint returns a report of all authentication logs for the organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_dateFrom-3'
        - $ref: '#/components/parameters/parameters_dateTo-3'
        - $ref: '#/components/parameters/authenticatableId'
        - $ref: '#/components/parameters/loginSuccessful'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/AuthenticationLogResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/authentication-log/queue:
    get:
      summary: Queue an export of the organisation authentication log report
      tags:
        - OrganisationReports
      operationId: actionQueueAuthenticationLogReport
      description: |
        This endpoint queues an export of all authentication logs for the organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_dateFrom-3'
        - $ref: '#/components/parameters/parameters_dateTo-3'
        - $ref: '#/components/parameters/authenticatableId'
        - $ref: '#/components/parameters/loginSuccessful'
      responses:
        '200':
          description: The request to queue the report was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/revenue-by-sales-channel:
    get:
      summary: Organisation revenue by sales channel report
      tags:
        - OrganisationReports
      operationId: getOrganisationRevenueBySalesChannelReport
      description: Get a report of revenue by sales channel for all sites in an organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_revenueDateFrom-10'
        - $ref: '#/components/parameters/parameters_revenueDateTo-10'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-6'
        - $ref: '#/components/parameters/parameters_submittedAtTo-6'
        - $ref: '#/components/parameters/parameters_itemDateFrom-3'
        - $ref: '#/components/parameters/parameters_itemDateTo-3'
        - $ref: '#/components/parameters/parameters_salesChannel'
        - $ref: '#/components/parameters/parameters_revenueCentre'
        - $ref: '#/components/parameters/parameters_siteId-46'
      responses:
        '200':
          $ref: '#/components/responses/OrganisationRevenueBySalesChannelResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/revenue-by-sales-channel/queue:
    get:
      summary: Queue an export of the organisation revenue by sales channel report.
      tags:
        - OrganisationReports
      operationId: actionQueueOrganisationRevenueBySalesChannelReport
      description: |
        This endpoint queues an export of the organisation revenue by sales channel report.
      parameters:
        - $ref: '#/components/parameters/parameters_revenueDateFrom-10'
        - $ref: '#/components/parameters/parameters_revenueDateTo-10'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-6'
        - $ref: '#/components/parameters/parameters_submittedAtTo-6'
        - $ref: '#/components/parameters/parameters_itemDateFrom-3'
        - $ref: '#/components/parameters/parameters_itemDateTo-3'
        - $ref: '#/components/parameters/parameters_salesChannel'
        - $ref: '#/components/parameters/parameters_revenueCentre'
      responses:
        '200':
          description: The request to queue the report was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/top-offerings:
    get:
      summary: Organisation revenue by centre report
      tags:
        - OrganisationReports
      operationId: getOrganisationTopOfferingsReport
      description: Get a report of top offerings across all sites in an organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_revenueDateFrom-10'
        - $ref: '#/components/parameters/parameters_revenueDateTo-10'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_offeringType-4'
      responses:
        '200':
          $ref: '#/components/responses/OrganisationTopOfferingsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/organisation/top-offerings/queue:
    get:
      summary: Queue an export of the organisation top offerings report.
      tags:
        - OrganisationReports
      operationId: actionQueueOrganisationTopOfferingsReport
      description: |
        This endpoint queues an export of the organisation top offerings report.
      parameters:
        - $ref: '#/components/parameters/parameters_revenueDateFrom-10'
        - $ref: '#/components/parameters/parameters_revenueDateTo-10'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_offeringType-4'
      responses:
        '200':
          description: The request to queue the report was successful
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/projected-membership-revenue:
    get:
      summary: List projected revenues for memberships
      operationId: listProjectedMembershipRevenue
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve the projected revenue from `Memberships` at a given date
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-47'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_date-9'
        - $ref: '#/components/parameters/membershipTypeIds'
        - $ref: '#/components/parameters/billingFrequency'
        - $ref: '#/components/parameters/manualPayments'
      responses:
        '200':
          description: The list of `ProjectedMembershipRevenue` resources was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListProjectedMembershipRevenueResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/projected-membership-revenue/queue:
    get:
      summary: Queue an export of the projected membership revenue report
      tags:
        - Reports
      operationId: actionQueueProjectedMembershipRevenueReport
      description: This endpoint queues an export of the projected membership revenue report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-47'
        - $ref: '#/components/parameters/parameters_date-9'
        - $ref: '#/components/parameters/membershipTypeIds'
        - $ref: '#/components/parameters/billingFrequency'
        - $ref: '#/components/parameters/manualPayments'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/projected-membership-revenue-by-month:
    get:
      summary: List projected revenues by month for memberships
      operationId: listProjectedMembershipRevenueByMonth
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve the projected revenue from `Memberships` at a given date for the following 12 calendar months
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-48'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_date-10'
        - $ref: '#/components/parameters/parameters_membershipTypeIds'
        - $ref: '#/components/parameters/parameters_billingFrequency'
        - $ref: '#/components/parameters/parameters_manualPayments'
      responses:
        '200':
          description: The list of `ProjectedMembershipRevenueByMonth` resources was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListProjectedMembershipRevenueByMonthResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/projected-membership-revenue-by-month/queue:
    get:
      summary: Queue an export of the projected membership revenue by month report
      tags:
        - Reports
      operationId: actionQueueProjectedMembershipRevenueByMonthReport
      description: This endpoint queues an export of the projected membership revenue by month report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-48'
        - $ref: '#/components/parameters/parameters_date-10'
        - $ref: '#/components/parameters/parameters_membershipTypeIds'
        - $ref: '#/components/parameters/parameters_billingFrequency'
        - $ref: '#/components/parameters/parameters_manualPayments'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/orders-sheet/queue:
    get:
      summary: Queue an export of the orders sheet
      tags:
        - Reports
      operationId: actionQueueOrdersSheet
      description: Queue a request to export the orders sheet
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-49'
        - $ref: '#/components/parameters/parameters_query-14'
        - $ref: '#/components/parameters/parameters_itemDate'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/membership-credits:
    get:
      summary: List membership credits
      operationId: listMembershipCredits
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a paginated list of membership credits.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-43'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          description: The list of items was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListMembershipCreditsResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/membership-credits/queue:
    get:
      summary: Queue an export of the membership credit report
      tags:
        - Reports
      operationId: actionQueueMembershipCreditsReport
      description: This endpoint queues an export of the membership credit report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-43'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/membership-credit-usage:
    get:
      summary: List membership credit usage
      operationId: listMembershipCreditUsage
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a paginated list of individual membership credit records,
        including their current status (redeemable, redeemed, revoked, or expired), the associated
        customer and membership details, and issuance/expiry dates. Unlike the membership credits
        summary report, this report returns one row per credit rather than aggregating by membership.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-50'
        - $ref: '#/components/parameters/parameters_status-9'
        - $ref: '#/components/parameters/parameters_membershipTypeId-2'
        - $ref: '#/components/parameters/membershipStatus'
        - $ref: '#/components/parameters/multiUse'
        - $ref: '#/components/parameters/issuedAtFrom'
        - $ref: '#/components/parameters/issuedAtTo'
        - $ref: '#/components/parameters/parameters_sort-4'
        - $ref: '#/components/parameters/sortDirectionQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          description: The list of items was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListMembershipCreditUsageResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/membership-credit-usage/queue:
    get:
      summary: Queue an export of the membership credit usage report
      tags:
        - Reports
      operationId: actionQueueMembershipCreditUsageReport
      description: This endpoint queues an export of the membership credit usage report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-50'
        - $ref: '#/components/parameters/parameters_status-9'
        - $ref: '#/components/parameters/parameters_membershipTypeId-2'
        - $ref: '#/components/parameters/membershipStatus'
        - $ref: '#/components/parameters/multiUse'
        - $ref: '#/components/parameters/issuedAtFrom'
        - $ref: '#/components/parameters/issuedAtTo'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/course-credits:
    get:
      summary: List course credits
      operationId: listCourseCredits
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a paginated list of individual course credit records,
        including their current status (redeemable, redeemed, revoked, or expired), the customer
        and course they belong to, key dates, and their monetary value. Course credits are
        customer credits issued from a course purchase at the given site. Totals summarise the
        outstanding and redeemed value of the matched credits so a site can reconcile its
        course-credit liability.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-51'
        - $ref: '#/components/parameters/parameters_courseTypeId'
        - $ref: '#/components/parameters/parameters_status-9'
        - $ref: '#/components/parameters/issuedAtFrom'
        - $ref: '#/components/parameters/issuedAtTo'
        - $ref: '#/components/parameters/parameters_sort-4'
        - $ref: '#/components/parameters/sortDirectionQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          description: The list of items was successfully retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListCourseCreditResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/course-credits/queue:
    get:
      summary: Queue an export of the course credit report
      tags:
        - Reports
      operationId: actionQueueCourseCreditsReport
      description: This endpoint queues an export of the course credit report.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-51'
        - $ref: '#/components/parameters/parameters_courseTypeId'
        - $ref: '#/components/parameters/parameters_status-9'
        - $ref: '#/components/parameters/issuedAtFrom'
        - $ref: '#/components/parameters/issuedAtTo'
      responses:
        '200':
          description: The export was successfully queued
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/kpi-stats:
    get:
      operationId: getKpiStatsReport
      summary: Get KPI stats report
      description: |
        Returns per-day basket statistics and range totals over a configurable date range (defaulting to the last 30 days). Shows total basket counts and average values, with website baskets (source=shop_v2) broken out separately. Per-day data includes an entry for every date in the requested range, even when no baskets exist for that day (zero-count entries are included). The summary provides aggregated totals across the entire date range. Requires the `DASHBOARDS_VIEW` permission.
      tags:
        - Reports
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
      responses:
        '200':
          $ref: '#/components/responses/KpiStatsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '403':
          $ref: '#/components/responses/Forbidden'
  /customers/memberships:
    get:
      summary: List Memberships
      tags:
        - Memberships
      operationId: listMemberships
      parameters:
        - $ref: '#/components/parameters/parameters_customerId'
        - $ref: '#/components/parameters/archived'
        - $ref: '#/components/parameters/parameters_siteId-52'
        - $ref: '#/components/parameters/parameters_status-10'
        - $ref: '#/components/parameters/membershipTypeIdDeprecated'
        - $ref: '#/components/parameters/parameters_membershipTypeIds-2'
        - $ref: '#/components/parameters/membershipRateIds'
        - $ref: '#/components/parameters/parameters_createdAtFrom-2'
        - $ref: '#/components/parameters/parameters_createdAtTo-2'
        - $ref: '#/components/parameters/nextBillingDateFrom'
        - $ref: '#/components/parameters/nextBillingDateTo'
        - $ref: '#/components/parameters/endDateFrom'
        - $ref: '#/components/parameters/endDateTo'
        - $ref: '#/components/parameters/attentionReason'
        - $ref: '#/components/parameters/parameters_manualPayments-2'
        - $ref: '#/components/parameters/parameters_billingFrequency-2'
        - $ref: '#/components/parameters/rateId'
        - $ref: '#/components/parameters/membershipNumber'
        - $ref: '#/components/parameters/externalRef'
        - $ref: '#/components/parameters/parameters_organisationId-3'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      description: |
        This endpoint lists the `Membership`s which are associated to the provided site.

        By default only active (non-archived) memberships are returned. Pass `archived=true`
        to retrieve archived (soft-deleted) memberships instead.
      responses:
        '200':
          $ref: '#/components/responses/ListMemberships'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a Membership
      tags:
        - Memberships
      operationId: createMembership
      description: |
        Use this endpoint to create a new `Membership`. A `Membership` always requires a `Customer`,
        but for convenience, you can pass `customer_data` to create the customer inline and attach
        the membership to the newly created customer.

        Unless you're authorised to do so, you'll only be permitted to create a membership for a
        private `MembershipType` and/or a non-default `MembershipRate` when you provide a valid
        `MembershipSignupToken` ID for the type and rate in question.

        The status of newly created memberships is always `reserved`. You'll need to make a request
        to the `confirmMembership` endpoint to update the status once the pro-rata or joining fee
        payment has been paid.
      parameters:
        - $ref: '#/components/parameters/onBehalfOf'
      requestBody:
        $ref: '#/components/requestBodies/CreateMembership'
      responses:
        '201':
          $ref: '#/components/responses/ShowMembership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/memberships/{membershipId}:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    get:
      summary: Show a membership
      description: |
        Use this endpoint to retrieve a `Membership` by its ID.
      tags:
        - Memberships
      operationId: getMembership
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Membership
      description: |
        Update mutable fields on an existing `Membership` such as its membership type, rate,
        start/end dates and external reference.
      tags:
        - Memberships
      operationId: updateMembership
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembership'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a Membership
      description: |
        Archives a `Membership`. Archived memberships are removed from the active list but
        their record is retained for reporting purposes.
      tags:
        - Memberships
      operationId: deleteMembership
      responses:
        '204':
          description: The membership was successfully archived.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/restore:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Restore a membership
      tags:
        - Memberships
      operationId: actionRestoreMembership
      description: |
        Restores an archived (soft-deleted) `Membership`, returning it to active use.

        The membership must currently be archived; restoring a membership that is not
        archived returns a `400` response.
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '400':
          description: The membership is not archived and cannot be restored
          content:
            application/json:
              schema:
                title: MembershipNotArchived
                type: object
                additionalProperties: false
                properties:
                  message:
                    type: string
                    description: A description of the error
                    example: This membership is not archived
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-types:
    get:
      summary: List MembershipTypes
      tags:
        - MembershipTypes
      operationId: listMembershipTypes
      description: |
        This endpoint lists the `MembershipType`s which are associated to the provided site.
      parameters:
        - $ref: '#/components/parameters/parameters_brand_id'
        - $ref: '#/components/parameters/parameters_site_id'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/public'
        - $ref: '#/components/parameters/auto_payments'
        - $ref: '#/components/parameters/terms'
        - $ref: '#/components/parameters/parameters_query-16'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListMembershipTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create MembershipType
      tags:
        - MembershipTypes
      operationId: createMembershipType
      description: |
        Use this endpoint to create a new `MembershipType`.
      requestBody:
        $ref: '#/components/requestBodies/CreateMembershipType'
      responses:
        '201':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-types/{membershipTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_membershipTypeId-3'
    get:
      summary: Show MembershipType
      tags:
        - MembershipTypes
      operationId: getMembershipType
      description: |
        This endpoint retrieves a `MembershipType` by its ID.
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update MembershipType
      tags:
        - MembershipTypes
      operationId: updateMembershipType
      description: |
        Use this endpoint to update a `MembershipType`.
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipType'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete MembershipType
      description: |
        Soft-deletes the given `MembershipType`. Existing memberships
        that reference this type are unaffected, but the type can no
        longer be selected for new memberships. Use the companion
        `restoreMembershipType` endpoint to undo.
      tags:
        - MembershipTypes
      operationId: deleteMembershipType
      responses:
        '204':
          description: The `MembershipType` was successfully soft-deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-types/{membershipTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_membershipTypeId-3'
    post:
      summary: Copy a MembershipType
      tags:
        - MembershipTypes
      operationId: actionCopyMembershipType
      description: |
        This endpoint copies an existing `MembershipType` by ID.
      requestBody:
        $ref: '#/components/requestBodies/CopyMembershipType'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-types/{membershipTypeId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/parameters_membershipTypeId-3'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a MembershipType
      description: Returns the localised `name`, `description`, and `terms` for the given locale.
      operationId: getMembershipTypeLocaleStrings
      tags:
        - MembershipTypes
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a MembershipType
      description: Sets the localised `name`, `description`, and/or `terms` for the given locale. Pass `null` to clear the translation and fall back to the default content.
      operationId: updateMembershipTypeLocaleStrings
      tags:
        - MembershipTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipTypeLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateMembershipTypeLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-rates:
    get:
      summary: List MembershipRates
      tags:
        - MembershipRates
      operationId: listMembershipRates
      description: |
        This endpoint lists the `MembershipRate`s which are associated to the provided site.
      parameters:
        - $ref: '#/components/parameters/parameters_membership_type_id'
        - $ref: '#/components/parameters/parameters_site_id-2'
        - $ref: '#/components/parameters/parameters_brand_id-2'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/parameters_query-17'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListMembershipRates'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a MembershipRate
      tags:
        - MembershipRates
      operationId: createMembershipRate
      description: |
        Use this endpoint to create a new `MembershipRate`. A `MembershipRate` belongs to a
        `MembershipType` and defines how members of that type are billed.
      requestBody:
        $ref: '#/components/requestBodies/CreateMembershipRate'
      responses:
        '201':
          $ref: '#/components/responses/ShowMembershipRate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-credit-rules:
    get:
      summary: List membership credit rules
      tags:
        - MembershipCreditRules
      operationId: listMembershipCreditRules
      description: |
        This endpoint retrieves all the membership credit rules associated with a brand, and is typically filtered by membership type.
      parameters:
        - $ref: '#/components/parameters/parameters_brandId'
        - $ref: '#/components/parameters/parameters_membershipTypeId-4'
        - $ref: '#/components/parameters/issueOnSignup'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListMembershipCreditRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a membership credit rule
      tags:
        - MembershipCreditRules
      operationId: createMembershipCreditRule
      description: |
        This endpoint creates a new membership credit rule for a membership type.
      requestBody:
        $ref: '#/components/requestBodies/CreateMembershipCreditRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowMembershipCreditRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-credit-rules/{creditRuleId}:
    parameters:
      - $ref: '#/components/parameters/creditRuleId'
    get:
      summary: Get a single membership credit rule
      tags:
        - MembershipCreditRules
      operationId: getMembershipCreditRule
      description: |
        This endpoint retrieves a single membership credit rule by its ID.
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipCreditRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a membership credit rule
      tags:
        - MembershipCreditRules
      operationId: updateMembershipCreditRule
      description: |
        This endpoint updates a membership credit rule.
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipCreditRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipCreditRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a membership credit rule
      tags:
        - MembershipCreditRules
      operationId: deleteMembershipCreditRule
      description: |
        This endpoint deletes a membership credit rule.
      responses:
        '204':
          description: The membership credit rule was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-credit-rules/{creditRuleId}/issue:
    parameters:
      - $ref: '#/components/parameters/creditRuleId'
    post:
      summary: Issue credits for all active memberships under a credit rule's membership type
      tags:
        - MembershipCreditRules
      operationId: actionIssueMembershipCreditRuleCredits
      description: |
        This endpoint will trigger an async job to issue credits for all active memberships
        under this credit rule's membership type. It will only issue credits if the customer
        doesn't already have an unredeemed, unexpired, unrevoked token issued by this rule.
      requestBody:
        description: Optional flags controlling which memberships get a credit issued.
        required: false
        content:
          application/json:
            schema:
              type: object
              title: ActionIssueMembershipCreditRuleCredits
              additionalProperties: false
              properties:
                include_upcoming:
                  type: boolean
                  description: |
                    When true, also issue credits to memberships that are
                    signed up under this credit rule's membership type but
                    haven't yet been billed for the current cycle —
                    effectively backfilling the credit for members who
                    joined after the rule fired. When false (default),
                    only memberships that are already in the active /
                    billing state receive a credit.
              required: []
      responses:
        '204':
          description: The credits were successfully issued
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/membership-charges/{chargeId}/payment:
    parameters:
      - $ref: '#/components/parameters/chargeId'
    post:
      summary: Record a manual payment against a charge
      tags:
        - Memberships
      operationId: actionAddMembershipChargePayment
      description: |
        This endpoint allows a manual (off-Trybe) payment to be recorded against a membership charge.
      requestBody:
        $ref: '#/components/requestBodies/AddMembershipChargePayment'
      responses:
        '200':
          $ref: '#/components/responses/MembershipChargeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/membership-charges/{chargeId}/process:
    parameters:
      - $ref: '#/components/parameters/chargeId'
    post:
      summary: Manually process a charge for a membership
      tags:
        - Memberships
      operationId: actionProcessMembershipCharge
      description: |
        This endpoint allows a membership charge to be processed manually.
      responses:
        '200':
          $ref: '#/components/responses/MembershipChargeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/membership-charges/{chargeId}/retry:
    parameters:
      - $ref: '#/components/parameters/chargeId'
    post:
      summary: Manually retry a charge for a membership
      tags:
        - Memberships
      operationId: actionRetryMembershipCharge
      description: |
        This endpoint allows a membership charge to be retried manually.
      responses:
        '200':
          $ref: '#/components/responses/MembershipChargeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/memberships/{membershipId}/sms:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Send an SMS message for a membership
      tags:
        - Memberships
      operationId: createMembershipSms
      description: |
        This endpoint sends an SMS message to a membership's lead member.
        Currently supports sending billing details request messages.
      requestBody:
        $ref: '#/components/requestBodies/SendMembershipSms'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipSms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/memberships/{membershipId}/sms/preview:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Preview an SMS message for a membership
      tags:
        - Memberships
      operationId: createMembershipSmsPreview
      description: |
        This endpoint previews an SMS message for a membership.
      requestBody:
        $ref: '#/components/requestBodies/PreviewMembershipSms'
      responses:
        '200':
          $ref: '#/components/responses/PreviewMembershipSms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /users:
    get:
      summary: Get all users
      description: |
        Use this endpoint to retrieve all users
      tags:
        - Users
      operationId: listAllUsers
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/organisationId'
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/query'
        - $ref: '#/components/parameters/twofaEnabled'
        - $ref: '#/components/parameters/twofaDisabled'
        - $ref: '#/components/parameters/managedBySso'
        - $ref: '#/components/parameters/notManagedBySso'
        - $ref: '#/components/parameters/includeInactive'
      responses:
        '200':
          $ref: '#/components/responses/ListUsers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a new user
      description: |
        This endpoint creates a new user in Trybe
      requestBody:
        $ref: '#/components/requestBodies/CreateUser'
      operationId: createUser
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/ShowUser'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /users/{userId}:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    get:
      summary: Get a user
      description: Use this endpoint to retrieve a user.
      operationId: getUser
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/ShowUser'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a user
      description: |
        This endpoint updates an API user in Trybe
      operationId: updateUser
      tags:
        - Users
      requestBody:
        $ref: '#/components/requestBodies/UpdateUser'
      responses:
        '200':
          $ref: '#/components/responses/ShowUser'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a user
      description: |
        This endpoint deletes a user in Trybe
      operationId: deleteUser
      tags:
        - Users
      responses:
        '204':
          description: No content
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /users/{userId}/roles:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    put:
      summary: Assign a role to the user
      description: Specify the role ID to assign to the user.
      tags:
        - Permissions
      operationId: actionAssignUserRole
      requestBody:
        $ref: '#/components/requestBodies/AssignRoleRequest'
      responses:
        '204':
          description: The role was successfully assigned.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a role from the user
      description: Specify the role ID to remove from the user.
      tags:
        - Permissions
      operationId: actionRemoveUserRole
      requestBody:
        $ref: '#/components/requestBodies/RemoveRoleRequest'
      responses:
        '204':
          description: The role was successfully removed.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /users/{userId}/site-roles:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    get:
      summary: Retrieve User Roles
      description: Use this endpoint to retrieve all the Roles a User has.
      operationId: listUserSiteRoles
      tags:
        - Users
      responses:
        '200':
          description: Roles were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListUserSiteRolesResponse
                allOf:
                  - $ref: '#/components/schemas/DataEnvelope'
                  - title: ListUserSiteRolesResponseData
                    type: object
                    additionalProperties: false
                    required:
                      - data
                    properties:
                      data:
                        description: An array of `UserSiteRole`s.
                        type: array
                        items:
                          title: UserSiteRole
                          description: The site user role
                          type: object
                          additionalProperties: false
                          required:
                            - permissions
                            - role
                            - role_id
                            - site
                            - site_id
                          properties:
                            permissions:
                              type: array
                              description: The array of permissions associated with this user site role.
                              uniqueItems: true
                              items:
                                type: string
                                description: The permission string.
                                example: users.view
                            role:
                              $ref: '#/components/schemas/Role'
                            role_id:
                              type: string
                              format: uuid
                              description: The ID of the site.
                            site:
                              $ref: '#/components/schemas/schemas_Site'
                            site_id:
                              type: string
                              format: uuid
                              description: The ID of the site.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Assign User to Role
      description: Use this endpoint to assign a Role to a User.
      operationId: actionAssignUserSiteRole
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: AssignUserSiteRole
              type: object
              additionalProperties: false
              required:
                - site_id
                - role_id
              properties:
                site_id:
                  type: string
                  description: |
                    Identifier of the site to grant the role at. Site roles
                    scope permissions to a single site; the user only
                    receives the role's permissions when acting on this
                    site. The caller's API key must have access to it.
                  example: beddda88-947d-4bd8-8f0c-828b187f93b2
                role_id:
                  type: string
                  description: |
                    Identifier of the role to assign. The role's
                    permissions apply only when the user is operating in
                    the context of the specified `site_id`.
                  example: beddda88-947d-4bd8-8f0c-828b187f93b3
      responses:
        '201':
          description: The role was successfully assigned.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Unassign User from Role
      description: Use this endpoint to remove a Role from a User.
      operationId: deleteUserSiteRole
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: DeleteUserSiteRole
              type: object
              additionalProperties: false
              required:
                - site_id
                - role_id
              properties:
                site_id:
                  type: string
                  description: |
                    Identifier of the site from which the role should be
                    removed. Only the assignment at this site is revoked;
                    the user's roles at other sites are unaffected.
                  example: beddda88-947d-4bd8-8f0c-828b187f93b2
                role_id:
                  type: string
                  description: |
                    Identifier of the role to revoke. Must match a role
                    currently assigned to the user at the given `site_id`;
                    no-op if the user does not hold this role at this site.
                  example: beddda88-947d-4bd8-8f0c-828b187f93b3
      responses:
        '204':
          description: The role was successfully removed.
        '400':
          $ref: '#/components/responses/ValidationFailed'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /users/{userId}/sites:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    get:
      summary: Get a user's Sites
      description: |
        Use this endpoint to get a user's Sites
      tags:
        - Users
      operationId: getUserSites
      responses:
        '200':
          description: The user's sites were successfully retrieved
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                title: SiteResponse
                readOnly: true
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Site'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /roles:
    get:
      summary: List Roles
      description: |
        This endpoint retrieves a list of all the roles for the given organisation.
        The roles are assigned to users to grant them permissions.
      tags:
        - Permissions
      operationId: listRoles
      parameters:
        - $ref: '#/components/parameters/parameters_query-18'
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListRoles'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a Role
      description: |
        This endpoint creates a role for the given organisation.
      tags:
        - Permissions
      operationId: createRole
      requestBody:
        $ref: '#/components/requestBodies/CreateRole'
      responses:
        '201':
          $ref: '#/components/responses/ShowRole'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /roles/{roleId}:
    parameters:
      - $ref: '#/components/parameters/roleId'
    get:
      summary: Show a Role
      tags:
        - Permissions
      operationId: getRole
      description: |
        This endpoint retrieves a role for the given organisation.
      responses:
        '200':
          $ref: '#/components/responses/ShowRole'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Role
      tags:
        - Permissions
      operationId: updateRole
      description: |
        This endpoint updates a role for the given organisation.
      requestBody:
        $ref: '#/components/requestBodies/UpdateRole'
      responses:
        '200':
          $ref: '#/components/responses/ShowRole'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a Role
      tags:
        - Permissions
      operationId: deleteRole
      description: |
        This endpoint soft deletes a role for the given organisation.
      responses:
        '204':
          description: The role was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /roles/{roleId}/copy:
    parameters:
      - $ref: '#/components/parameters/roleId'
    post:
      summary: Copy a Role
      tags:
        - Permissions
      operationId: actionCopyRole
      description: |
        This endpoint copies an existing role by ID.
      requestBody:
        $ref: '#/components/requestBodies/CopyRole'
      responses:
        '200':
          $ref: '#/components/responses/ShowRole'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /roles/{roleId}/restore:
    parameters:
      - $ref: '#/components/parameters/roleId'
    post:
      summary: Restore a Role
      description: |
        This endpoint restores an archived (soft-deleted) role by ID.
      tags:
        - Permissions
      operationId: restoreRole
      responses:
        '200':
          $ref: '#/components/responses/ShowRole'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /permissions:
    get:
      summary: List Permissions
      description: |
        This endpoint retrieves a list of all possible permissions which can be assigned to a role.
      tags:
        - Permissions
      operationId: listPermissions
      responses:
        '200':
          $ref: '#/components/responses/ListPermissions'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/commission-packages:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId'
    get:
      summary: List CommissionPackages
      tags:
        - CommissionPackages
      operationId: listCommissionPackages
      description: |
        Use this endpoint to retrieve a list of `CommissionPackage`s for a site.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCommissionPackages'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create CommissionPackage
      tags:
        - CommissionPackages
      operationId: createCommissionPackage
      description: |
        Use this endpoint to create a new `CommissionPackage` for a site.
      requestBody:
        $ref: '#/components/requestBodies/CreateCommissionPackage'
      responses:
        '201':
          $ref: '#/components/responses/ShowCommissionPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/commission-packages/{commissionPackageId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId'
      - $ref: '#/components/parameters/commissionPackageId'
    get:
      summary: Show CommissionPackage
      tags:
        - CommissionPackages
      operationId: getCommissionPackage
      description: |
        Use this endpoint to retrieve a single `CommissionPackage`.
      responses:
        '200':
          $ref: '#/components/responses/ShowCommissionPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update CommissionPackage
      tags:
        - CommissionPackages
      operationId: updateCommissionPackage
      description: |
        Use this endpoint to update a `CommissionPackage`.
      requestBody:
        $ref: '#/components/requestBodies/UpdateCommissionPackage'
      responses:
        '200':
          $ref: '#/components/responses/ShowCommissionPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete CommissionPackage
      tags:
        - CommissionPackages
      operationId: deleteCommissionPackage
      description: |
        Use this endpoint to delete a `CommissionPackage`.
      responses:
        '204':
          description: The `CommissionPackage` was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/user-commission-assignments:
    get:
      summary: List UserCommissionAssignments
      tags:
        - CommissionPackages
      operationId: listUserCommissionAssignments
      description: |
        Use this endpoint to retrieve a list of `UserCommissionAssignment`s,
        optionally filtered by site or user. Each assignment attaches a
        `CommissionPackage` to a plain `User` at a site, for staff who earn
        commission but aren't modelled as a `Practitioner`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/parameters_userId-3'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListUserCommissionAssignments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create UserCommissionAssignment
      tags:
        - CommissionPackages
      operationId: createUserCommissionAssignment
      description: |
        Use this endpoint to assign a `CommissionPackage` to a `User` at a
        site. Fails with `422` if the user already has an assignment at
        that site — update the existing `UserCommissionAssignment` instead.
      requestBody:
        $ref: '#/components/requestBodies/CreateUserCommissionAssignment'
      responses:
        '201':
          $ref: '#/components/responses/ShowUserCommissionAssignment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/user-commission-assignments/{userCommissionAssignmentId}:
    parameters:
      - $ref: '#/components/parameters/userCommissionAssignmentId'
    get:
      summary: Show UserCommissionAssignment
      tags:
        - CommissionPackages
      operationId: getUserCommissionAssignment
      description: |
        Use this endpoint to retrieve a single `UserCommissionAssignment`.
      responses:
        '200':
          $ref: '#/components/responses/ShowUserCommissionAssignment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update UserCommissionAssignment
      tags:
        - CommissionPackages
      operationId: updateUserCommissionAssignment
      description: |
        Use this endpoint to change the `CommissionPackage` assigned to a
        `UserCommissionAssignment`. The assignment's `user_id` and
        `site_id` cannot be changed — delete and recreate the assignment
        instead.
      requestBody:
        $ref: '#/components/requestBodies/UpdateUserCommissionAssignment'
      responses:
        '200':
          $ref: '#/components/responses/ShowUserCommissionAssignment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete UserCommissionAssignment
      tags:
        - CommissionPackages
      operationId: deleteUserCommissionAssignment
      description: |
        Use this endpoint to remove a `UserCommissionAssignment`. The user
        stops earning commission under the assigned package going forward;
        past commission calculations are unaffected.
      responses:
        '204':
          description: The `UserCommissionAssignment` was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/offering-sets:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId'
    get:
      summary: List OfferingSets
      tags:
        - OfferingSets
      operationId: listOfferingSets
      description: |
        Use this endpoint to retrieve a list of `OfferingSet`s for a site.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListOfferingSets'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create OfferingSet
      tags:
        - OfferingSets
      operationId: createOfferingSet
      description: |
        Use this endpoint to create a new `OfferingSet` for a site.
      requestBody:
        $ref: '#/components/requestBodies/CreateOfferingSet'
      responses:
        '201':
          $ref: '#/components/responses/ShowOfferingSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/offering-sets/{offeringSetId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId'
      - $ref: '#/components/parameters/offeringSetId'
    get:
      summary: Show OfferingSet
      tags:
        - OfferingSets
      operationId: getOfferingSet
      description: |
        Use this endpoint to retrieve a single `OfferingSet`.
      responses:
        '200':
          $ref: '#/components/responses/ShowOfferingSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update OfferingSet
      tags:
        - OfferingSets
      operationId: updateOfferingSet
      description: |
        Use this endpoint to update an `OfferingSet`.
      requestBody:
        $ref: '#/components/requestBodies/UpdateOfferingSet'
      responses:
        '200':
          $ref: '#/components/responses/ShowOfferingSet'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete OfferingSet
      tags:
        - OfferingSets
      operationId: deleteOfferingSet
      description: |
        Use this endpoint to delete an `OfferingSet`.
      responses:
        '204':
          description: The `OfferingSet` was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointment-enquiries/{appointmentEnquiryId}:
    parameters:
      - $ref: '#/components/parameters/parameters_appointmentEnquiryId'
    get:
      summary: Show an Appointment Enquiry
      tags:
        - AppointmentEnquiries
      description: |
        Use this endpoint to retrieve a single `AppointmentEnquiry` by its
        ID. The response includes the enquiry's current `status`
        (`received`, `confirmed` or `cancelled`), the time window the
        enquiry covers (`time_from` and `time_to`), and a `can_confirm`
        flag indicating whether the requested appointment can currently be
        booked.

        This is typically used after listing enquiries via
        [`listAppointmentEnquiries`](/endpoints/AppointmentEnquiries#listAppointmentEnquiries)
        to refresh availability before calling
        [`actionConfirmAppointmentEnquiry`](#actionConfirmAppointmentEnquiry).
      operationId: getAppointmentEnquiry
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentEnquiry'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointment-slots/{appointmentTypeId}/{date}:
    parameters:
      - $ref: '#/components/parameters/parameters_appointmentTypeId-3'
      - $ref: '#/components/parameters/parameters_date-11'
    get:
      summary: List appointment slots on a single date
      tags:
        - OfferingAvailability
      description: |
        Use this endpoint to list every potential start time for a given
        `AppointmentType` on a single date, together with each slot's
        bookability metadata.

        The response is an array of `AppointmentSlot` entries. Each slot
        includes the start and end time, the duration and end buffer, the
        practitioners and rooms that could be used to deliver it, the
        quantity currently available (`quantity_available`) versus the
        theoretical maximum (`total_quantity`), and the price in the
        smallest currency unit. Slots that aren't currently bookable expose
        a machine-readable `no_availability_reason` (e.g. `time_passed`,
        `no_practitioners_available`, `not_yet_bookable`) and a
        human-readable `no_availability_message`.

        To check availability across a sliding date-time window — useful
        for appointment enquiries where the customer is flexible on date —
        use
        [`actionCheckAppointmentEnquiryAvailability`](/endpoints/Availability#actionCheckAppointmentEnquiryAvailability)
        instead.
      operationId: listAppointmentSlots
      parameters:
        - $ref: '#/components/parameters/parameters_practitionerId-8'
        - $ref: '#/components/parameters/quantity'
      responses:
        '200':
          $ref: '#/components/responses/ListAppointmentSlots'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/area-booking-slots/{areaBookingTypeId}:
    parameters:
      - $ref: '#/components/parameters/parameters_areaBookingTypeId'
    get:
      summary: List area-booking slots across a date range
      tags:
        - OfferingAvailability
      description: |
        Use this endpoint to list every potential start time for a given
        `AreaBookingType` across a date range, with each slot's pricing
        and availability metadata.

        The response contains an array of `AreaBookingSlot` entries. Each
        slot lists the start and end time, the duration in minutes, the
        areas that could deliver it, the quantity currently available
        versus the theoretical maximum, and the price in the smallest
        currency unit. Slots that aren't currently bookable include a
        machine-readable `no_availability_reason` (e.g. `time_passed`,
        `no_areas_available`, `not_yet_bookable`) and a human-readable
        `no_availability_message` you can surface in your UI.

        For single-date appointment availability, see
        [`listAppointmentSlots`](#listAppointmentSlots) or
        [`getTableReservationSlots`](#getTableReservationSlots).
      operationId: listAreaBookingSlots
      parameters:
        - $ref: '#/components/parameters/parameters_dateFrom-4'
        - $ref: '#/components/parameters/parameters_dateTo-4'
        - $ref: '#/components/parameters/parameters_quantity'
        - $ref: '#/components/parameters/areaId'
      responses:
        '200':
          $ref: '#/components/responses/ListAreaBookingSlots'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/sites/{siteId}/integrations/adyen/onboarding-link:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/adyen/setup-details:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/adyen/setup-details/submit:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/adyen/setup-status:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/adyen/terminals:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/adyen/terminals/{terminalId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/terminalId'
        required: true
  /shop/sites/{siteId}/integrations/avvio:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/avvio/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/avvio/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/avvio/import-room-types:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/avvio/settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/booking-engine/age-categories:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/booking-engine/rates:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/giftpro/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/giftpro/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/giftpro/settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/guestline:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/guestline/credentials:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/guestline/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/guestline/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/guestline/payment-type-mappings/{customPaymentTypeId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_customPaymentTypeId'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/guestline/revenue-centre-mappings/{revenueCentre}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_revenueCentre-2'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/guestline/settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/hotsoft:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/credentials:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/ohip/transaction-codes:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/pms-settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/pms/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/pms/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/appointments-v2/queue:
    get:
      summary: Queue an export of the appointments-v2 list
      description: |
        Queues a background job that exports the same appointment list
        returned by `GET /shop/appointments-v2` as a CSV download. The
        `-v2` endpoint sources its data from the order-item store rather
        than the legacy appointments collection, which means it can apply
        a richer set of filters (sales channel, order label, brand, etc.)
        and reflects the same totals shown in revenue reports.

        The response returns a `QueuedJob` resource that you can poll via
        `GET /shop/queued-jobs/{queuedJobId}` to check progress and fetch
        the `download_url` once ready.

        All filters supported by the list endpoint are accepted here and
        are applied to the export.
      operationId: queueAppointmentsV2
      tags:
        - Appointments
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/orderSubmittedAtFrom'
        - $ref: '#/components/parameters/orderSubmittedAtTo'
        - $ref: '#/components/parameters/practitionerId'
        - $ref: '#/components/parameters/roomId'
        - $ref: '#/components/parameters/parameters_zoneId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/appointments/queue:
    get:
      summary: Queue an export of the appointments list
      description: |
        Queues a background job that exports the same `Appointment` list
        returned by `GET /shop/appointments` as a CSV download. Use this
        when the result set is too large to retrieve synchronously, or when
        you want the export delivered to the calling user as a downloadable
        file.

        The response returns a `QueuedJob` resource you can poll via
        `GET /shop/queued-jobs/{queuedJobId}`. Once the job has finished,
        its `download_url` becomes available and the CSV can be streamed.

        All filters supported by the list endpoint (date range, order
        submitted range, practitioner, room, zone) are accepted here and
        are applied to the export.
      operationId: queueAppointments
      tags:
        - Appointments
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/orderSubmittedAtFrom'
        - $ref: '#/components/parameters/orderSubmittedAtTo'
        - $ref: '#/components/parameters/practitionerId'
        - $ref: '#/components/parameters/roomId'
        - $ref: '#/components/parameters/parameters_zoneId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/availability-details:
    get:
      summary: Get availability details for a date
      description: |
        Returns an exhaustive availability snapshot for a single site/date,
        combining opening hours, calendar availability, practitioner and
        room schedules, equipment, and the periods already occupied by
        existing bookings or blocks.

        The endpoint powers Trybe's calendar day view and the booking
        workflow's "explain" panel — the same payload is used to render
        why a slot is or isn't bookable.

        Scope the response to a single offering by supplying both
        `offering_type` and `offering_id`. When omitted, the response
        includes every practitioner, room and equipment item at the site
        and skips offering-specific calendars.

        The current user must have the `reservations.manage` permission on
        the site to call this endpoint.
      operationId: getAvailabilityDetails
      tags:
        - Availability
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/parameters_date-12'
        - $ref: '#/components/parameters/parameters_offeringType-5'
        - $ref: '#/components/parameters/parameters_offeringId-6'
      responses:
        '200':
          description: The availability details were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AvailabilityDetailsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/calendar-occupancy:
    get:
      summary: Get calendar occupancy
      description: |
        Returns occupancy metrics for the operator calendar on a given
        date. The response counts the guests covered by all
        confirmed/waitlisted offerings (appointments, area bookings, and
        sessions) that fall within the date — bucketed by hour, by
        selected view, and as a single daily total.

        Occupancy is gated by the `occupancy_overview` feature flag. If
        the flag is off for the site, the underlying data resolves to
        `null`. Filter results by `view_type` (and optionally `zone_id`)
        to constrain the calculation to a single resource lane.
      operationId: getCalendarOccupancy
      tags:
        - CalendarEvents
      parameters:
        - $ref: '#/components/parameters/date'
        - $ref: '#/components/parameters/events'
        - $ref: '#/components/parameters/viewType'
        - $ref: '#/components/parameters/zoneId'
        - $ref: '#/components/parameters/parameters_siteId'
      responses:
        '200':
          description: Calendar occupancy successfully retrieved.
          content:
            application/json:
              schema:
                title: GetCalendarOccupancyResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    title: CalendarOccupancy
                    type: object
                    additionalProperties: false
                    nullable: true
                    description: |
                      Occupancy figures for the requested date, or `null`
                      when the `occupancy_overview` feature flag is off.
                    required:
                      - occupancy_for_view
                      - occupancy_per_day
                      - occupancy_per_hour
                    properties:
                      occupancy_for_view:
                        type: number
                        description: |
                          Guests covered by the filtered events for the
                          currently-selected view (e.g. all appointments
                          when `view_type=practitioner`).
                        example: 42
                      occupancy_per_day:
                        type: number
                        description: |
                          Site-wide guest count for the day across every
                          offering type. Independent of `view_type`.
                        example: 87
                      occupancy_per_hour:
                        type: array
                        description: |
                          Guests in scope keyed by hour-of-day, ascending.
                          Hours without bookings are omitted.
                        items:
                          title: CalendarOccupancyPerHour
                          type: object
                          additionalProperties: false
                          required:
                            - guests
                            - time
                          properties:
                            guests:
                              type: number
                              description: Guests covered in this hour bucket.
                              example: 6
                            time:
                              type: string
                              description: |
                                Start of the hour bucket as a 24-hour
                                `HH:mm` string in the site's local
                                timezone.
                              example: '09:00'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/calendar-resources:
    get:
      summary: List calendar resources for a date
      description: |
        Returns the resources displayed alongside the operator calendar
        for a given date — the lanes you book against. The response
        bundles:

        - The site's **opening hours** for the date, expressed as one or
          more open periods (a site can have split shifts).
        - All `Zone`s configured at the site (used to filter the
          calendar by area of the venue).
        - Every `BookableArea`, `Practitioner`, and `Room` at the site,
          each enriched with the resource's scheduled availability for
          the requested date and (for practitioners) any custom
          availability overrides that apply.

        Pass `zone_id` to restrict the resource lanes to a single zone;
        omitting it returns every resource at the site. The endpoint is
        typically called once per calendar render and refreshed when the
        operator changes date.
      operationId: listCalendarResources
      tags:
        - CalendarEvents
      parameters:
        - $ref: '#/components/parameters/date'
        - $ref: '#/components/parameters/zoneId'
        - $ref: '#/components/parameters/parameters_siteId'
      responses:
        '200':
          description: Calendar resources successfully retrieved.
          content:
            application/json:
              schema:
                title: ListCalendarResourcesResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    title: CalendarResources
                    type: object
                    additionalProperties: false
                    required:
                      - areas
                      - opening_hours
                      - practitioners
                      - rooms
                      - zones
                    properties:
                      opening_hours:
                        type: array
                        description: |
                          One or more open periods for the site on the
                          requested date. A site with a split shift will
                          return multiple non-overlapping periods.
                        items:
                          title: CalendarResourcesOpeningHoursPeriod
                          type: object
                          additionalProperties: true
                          required:
                            - start_time
                            - end_time
                          properties:
                            start_time:
                              type: string
                              format: date-time
                              description: ISO-8601 start of the open period.
                              example: '2026-05-23T08:00:00+01:00'
                            end_time:
                              type: string
                              format: date-time
                              description: ISO-8601 end of the open period.
                              example: '2026-05-23T20:00:00+01:00'
                      zones:
                        type: array
                        description: |
                          Every zone configured at the site, regardless of
                          whether the request was filtered by `zone_id`.
                        items:
                          title: CalendarResourcesZone
                          type: object
                          additionalProperties: true
                          required:
                            - id
                            - name
                          properties:
                            id:
                              type: string
                              example: 6622d459e7c1c2f0ff31c3f3
                            name:
                              type: string
                              example: Spa
                      areas:
                        type: array
                        description: |
                          `BookableArea` lanes scheduled for the date,
                          each carrying the area's `day_scheduled_availability` slots.
                        items:
                          title: CalendarResourcesArea
                          type: object
                          additionalProperties: true
                          required:
                            - id
                          properties:
                            id:
                              type: string
                              example: 6622e1f3ab50c4baa0f1d4a2
                            slots:
                              type: array
                              description: The area's scheduled availability windows for the date.
                              items:
                                title: CalendarResourcesAreaSlot
                                type: object
                                additionalProperties: true
                                required:
                                  - start_time
                                  - end_time
                                properties:
                                  start_time:
                                    type: string
                                    format: date-time
                                    description: ISO-8601 start of the available window.
                                    example: '2026-05-23T09:00:00+01:00'
                                  end_time:
                                    type: string
                                    format: date-time
                                    description: ISO-8601 end of the available window.
                                    example: '2026-05-23T17:00:00+01:00'
                      practitioners:
                        type: array
                        description: |
                          Practitioner lanes scheduled for the date, with
                          their rota, scheduled slots, and any custom
                          availability rules that apply.
                        items:
                          title: CalendarResourcesPractitioner
                          type: object
                          additionalProperties: true
                          required:
                            - id
                          properties:
                            id:
                              type: string
                              example: 6622aabb11cc22dd33ee44ff
                            slots:
                              type: array
                              description: The practitioner's working windows for the date.
                              items:
                                title: CalendarResourcesPractitionerSlot
                                type: object
                                additionalProperties: true
                                required:
                                  - start_time
                                  - end_time
                                properties:
                                  start_time:
                                    type: string
                                    format: date-time
                                    description: ISO-8601 start of the working window.
                                    example: '2026-05-23T09:00:00+01:00'
                                  end_time:
                                    type: string
                                    format: date-time
                                    description: ISO-8601 end of the working window.
                                    example: '2026-05-23T17:00:00+01:00'
                                  room_segments:
                                    type: array
                                    description: |
                                      Room assignments within this working window.
                                      Each entry covers a contiguous sub-range of the
                                      slot and links it to a specific room.
                                    items:
                                      title: CalendarResourcesPractitionerRoomSegment
                                      type: object
                                      additionalProperties: false
                                      required:
                                        - id
                                        - room_id
                                        - start_time
                                        - end_time
                                      properties:
                                        id:
                                          type: string
                                          format: object-id
                                          description: Unique identifier of the room assignment.
                                          example: 6622ff00112233445566aabb
                                        room_id:
                                          type: string
                                          format: object-id
                                          nullable: true
                                          description: The room assigned for this segment, or `null` for unassigned windows.
                                          example: 6622cc55ddeeff0011223344
                                        start_time:
                                          type: string
                                          format: date-time
                                          description: ISO-8601 start of the segment.
                                          example: '2026-05-23T09:00:00+01:00'
                                        end_time:
                                          type: string
                                          format: date-time
                                          description: ISO-8601 end of the segment.
                                          example: '2026-05-23T13:00:00+01:00'
                                        offerings:
                                          type: array
                                          description: |
                                            The offerings the practitioner is
                                            restricted to during this segment.
                                            An empty array (or omitted) means
                                            the practitioner may be booked for
                                            any offering during this window.
                                          items:
                                            $ref: '#/components/schemas/OfferingIdentifier'
                      rooms:
                        type: array
                        description: |
                          Room lanes scheduled for the date, each with
                          the room's `day_scheduled_availability` slots.
                        items:
                          title: CalendarResourcesRoom
                          type: object
                          additionalProperties: true
                          required:
                            - id
                          properties:
                            id:
                              type: string
                              example: 6622cc55ddeeff0011223344
                            slots:
                              type: array
                              description: The room's scheduled availability windows for the date.
                              items:
                                title: CalendarResourcesRoomSlot
                                type: object
                                additionalProperties: true
                                required:
                                  - start_time
                                  - end_time
                                properties:
                                  start_time:
                                    type: string
                                    format: date-time
                                    description: ISO-8601 start of the available window.
                                    example: '2026-05-23T09:00:00+01:00'
                                  end_time:
                                    type: string
                                    format: date-time
                                    description: ISO-8601 end of the available window.
                                    example: '2026-05-23T17:00:00+01:00'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/my-notification-config:
    get:
      summary: Get the authenticated user's notification config
      description: |
        Returns the authenticated user's per-site automated-report
        subscription state. Today this only exposes the **end-of-day
        summary** preference — whether the calling user is currently a
        recipient of the daily end-of-day email for the site.

        The site is resolved from the request authentication context; no
        `site_id` query parameter is required. Sub-resources under
        `/shop/my-notification-config` toggle individual subscriptions.
      operationId: getMyNotificationConfig
      tags:
        - Users
      responses:
        '200':
          description: The authenticated user's notification config.
          content:
            application/json:
              schema:
                title: GetMyNotificationConfigResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    title: MyNotificationConfig
                    type: object
                    additionalProperties: false
                    required:
                      - automated_reports
                    properties:
                      automated_reports:
                        title: MyNotificationConfigAutomatedReports
                        type: object
                        additionalProperties: false
                        description: |
                          The user's per-report subscription flags. Each
                          key is `true` when the user is a recipient of
                          that automated report at the current site.
                        required:
                          - end_of_day_summary
                        properties:
                          end_of_day_summary:
                            type: boolean
                            description: |
                              Whether the user receives the site's daily
                              end-of-day summary email.
                            example: true
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/my-notification-config/end-of-day-summary:
    post:
      summary: Subscribe to the end-of-day summary
      description: |
        Adds the authenticated user as a recipient of the site's
        end-of-day summary email — the daily wrap-up report sent to
        subscribed operators after close of business.

        Calls are idempotent: re-subscribing an already-subscribed user
        is a no-op and still returns `204 No Content`. The site is
        resolved from the request authentication context.
      operationId: createMyEndOfDaySummarySubscription
      tags:
        - Users
      responses:
        '204':
          description: The user is now subscribed to the end-of-day summary.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    delete:
      summary: Unsubscribe from the end-of-day summary
      description: |
        Removes the authenticated user from the site's end-of-day
        summary email recipients. Calls are idempotent: unsubscribing a
        user who isn't subscribed is a no-op and still returns
        `204 No Content`. The site is resolved from the request
        authentication context.
      operationId: deleteMyEndOfDaySummarySubscription
      tags:
        - Users
      responses:
        '204':
          description: The user is no longer subscribed to the end-of-day summary.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/orders/{orderId}/items/{itemId}/package-items/{packageItemId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
      - $ref: '#/components/parameters/parameters_packageItemId'
    put:
      summary: Update a package item on a package order item
      description: |
        Updates the scheduling configuration of a single child item within
        a parent package order item — for example moving the massage slot
        of a spa day to a different practitioner, time, or room.

        The payload accepts the same scheduling fields used when adding a
        package item via `POST /shop/orders/{orderId}/items/{itemId}/package-items`.
        Set fields you want to change; omitted fields are left as-is.

        The update is routed through the availability layer, so room,
        practitioner and equipment conflicts are validated. The order
        totals are recalculated and the refreshed parent item is returned.
      tags:
        - Orders
      operationId: updateOrderItemPackageItem
      requestBody:
        description: The fields to update on the package item.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PackageItemChoiceOption'
      responses:
        '200':
          $ref: '#/components/responses/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a package item from a package order item
      description: |
        Removes a single child item from a parent package line item — for
        example dropping the massage out of a spa day, or removing one
        class booking from a multi-class package. If the child item is a
        booking the underlying booking is cancelled and any held resources
        (practitioner, room, equipment) are released; if it is a purchase
        it is voided.

        The parent package item is left in place — even if every child is
        removed — so that the package can later be re-populated by adding
        new package items via `POST /shop/orders/{orderId}/items/{itemId}/package-items`.
        The order's totals are recalculated immediately.
      tags:
        - Orders
      operationId: deleteOrderItemPackageItem
      responses:
        '204':
          description: The package item was successfully removed.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/items/{itemId}/price:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
    put:
      summary: Override an order item's price
      description: |
        Sets a manual price override on a line item. The supplied `price`
        becomes the line's selling price, replacing the computed value
        derived from price rules, package allocations and promotional
        discounts. The new price must be **higher** than the item's
        original computed price — to lower the price, apply an
        `OrderDiscount` instead.

        The order's totals are recalculated synchronously and the refreshed
        item is returned. Use `DELETE` on the same URL to clear the
        override and revert to the computed price.
      tags:
        - Orders
      operationId: updateOrderItemPrice
      requestBody:
        description: The new price to set on the line item.
        required: true
        content:
          application/json:
            schema:
              title: UpdateOrderItemPrice
              type: object
              additionalProperties: false
              required:
                - price
              properties:
                price:
                  type: integer
                  minimum: 0
                  description: |
                    The new price of the item, in the smallest denomination
                    of the order's currency (e.g. pence, cents). Must be
                    strictly greater than the item's currently computed
                    price.
                  example: 2800
      responses:
        '200':
          $ref: '#/components/responses/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Reset an order item's price override
      description: |
        Clears any manual price override applied to the line item and
        reverts it to its computed price — i.e. the price that would have
        been charged based on the underlying offering's price rules, any
        promo codes, and any package allocation. Use this to undo an
        earlier override (set via `PUT /shop/orders/{orderId}/items/{itemId}/price`)
        when the customer changes their mind, the override was applied to
        the wrong line, or a discount has rendered the override moot.

        The order's totals are recalculated synchronously and the
        refreshed item is returned.
      tags:
        - Orders
      operationId: deleteOrderItemPrice
      responses:
        '200':
          $ref: '#/components/responses/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/vouchers/{voucherCode}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/voucherCode'
    delete:
      summary: Remove a voucher from an order
      description: |
        Detaches the given voucher from the order and refunds the
        redemption back onto the voucher's remaining balance. Use this
        when a voucher has been mistakenly applied — typically immediately
        after the customer says "actually, can you take that off?" — or
        when a refund flow needs to release the voucher value so it can
        be applied to a different order. The voucher itself is not
        cancelled; only its association with this order is removed.

        The order's totals are recalculated synchronously. If the voucher
        was the sole source of payment, the order will fall back to an
        outstanding balance equal to the voucher's previous contribution.
      tags:
        - Orders
      operationId: deleteOrderVoucher
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/appointment-tags:
    get:
      summary: List Appointment Tags
      tags:
        - Organisations
      operationId: listOrganisationAppointmentTags
      description: |
        Returns a paginated list of every appointment tag that belongs to
        the organisation. Tags are returned in creation order; use the
        pagination parameters to walk through large result sets.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListAppointmentTags'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an Appointment Tag
      tags:
        - Organisations
      operationId: createOrganisationAppointmentTag
      description: |
        Create a new appointment tag against the given organisation. The
        tag becomes immediately available to every site under the
        organisation and can subsequently be attached to appointment types.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      requestBody:
        $ref: '#/components/requestBodies/CreateAppointmentTag'
      responses:
        '201':
          $ref: '#/components/responses/ShowAppointmentTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/appointment-tags/{appointmentTagId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/appointmentTagId'
    get:
      summary: Get an Appointment Tag
      tags:
        - Organisations
      operationId: getOrganisationAppointmentTag
      description: |
        Returns the details of a single appointment tag, including its
        display name and the organisation it belongs to.
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Appointment Tag
      tags:
        - Organisations
      operationId: updateOrganisationAppointmentTag
      description: |
        Updates the display name of an existing appointment tag. The new
        name is reflected immediately wherever the tag is used in the
        admin UI and in reports.
      requestBody:
        description: The fields to update on the appointment tag.
        required: true
        content:
          application/json:
            schema:
              title: UpdateOrganisationAppointmentTag
              type: object
              additionalProperties: false
              required:
                - name
              properties:
                name:
                  type: string
                  description: |
                    Display name of the tag, shown to staff in the admin
                    UI and used when grouping appointment types in reports.
                    1-120 characters; must not contain HTML.
                  example: Signature
      responses:
        '200':
          $ref: '#/components/responses/ShowAppointmentTag'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an Appointment Tag
      tags:
        - Organisations
      operationId: deleteOrganisationAppointmentTag
      description: |
        Permanently deletes the appointment tag. The tag is removed from
        every appointment type it was previously attached to; existing
        bookings are not affected.
      responses:
        '204':
          description: The appointment tag was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/reports/adyen-fees:
    get:
      summary: Get the Adyen fees report
      operationId: getAdyenFeesReport
      tags:
        - Reports
      description: |
        Use this endpoint to retrieve a breakdown of the Adyen processing
        fees that have been deducted from captured payments over a given
        date range. Each row represents one Adyen payment and includes the
        component fees (commission, markup, scheme, interchange and
        processing) along with the payment metadata.

        The endpoint supports content negotiation: send `Accept: text/csv`
        (or append `.csv` to the URL where supported) to receive the report
        as a CSV download instead of JSON. The CSV variant requires the
        `reports.download` permission, whereas the JSON variant requires
        `reports.view`.

        When `date_from` and `date_to` are omitted, the report defaults to
        the current calendar month in the site's timezone.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-53'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
      responses:
        '200':
          description: The Adyen fees report was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListAdyenFeesReportResponse'
            text/csv:
              schema:
                type: string
                format: binary
                description: |
                  A CSV file containing one row per Adyen payment in the
                  requested period.
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/reports/hotel-package-items/refresh:
    get:
      summary: Refresh the hotel package items report
      operationId: actionRefreshHotelPackageItemsReport
      tags:
        - Reports
      description: |
        Use this endpoint to trigger a refresh of the hotel package items
        report. The report is regenerated asynchronously in the background
        and emailed to the configured recipients when ready; this endpoint
        returns immediately once the job has been queued.

        Because the underlying job is queued, calling this endpoint multiple
        times in quick succession may produce more than one delivery of the
        report. Wait for the previous email to arrive before retrying.
      responses:
        '204':
          description: |
            The refresh job was successfully dispatched. The report will be
            delivered asynchronously once it has finished generating.
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/partner-orders:
    get:
      summary: Export the partner orders report
      operationId: listPartnerOrders
      tags:
        - Reports
      description: |
        Use this endpoint to download a CSV export of every order placed
        through a specific partner. Each row corresponds to one order in
        the partner's pipeline, sorted by submission date (most recent
        first); when a `query` is supplied the rows are ordered by search
        relevance instead.

        Generating the file is synchronous, so for partners with very large
        order volumes prefer the [queue](#operation/queuePartnerOrdersExport)
        variant of this endpoint, which renders the report on a background
        worker and notifies you when it is ready.

        Requires the `admin.sites.manage` permission.
      parameters:
        - $ref: '#/components/parameters/partnerId'
        - $ref: '#/components/parameters/parameters_siteId-54'
        - $ref: '#/components/parameters/parameters_customerId-2'
        - $ref: '#/components/parameters/parameters_status-11'
        - $ref: '#/components/parameters/parameters_query-19'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-7'
        - $ref: '#/components/parameters/parameters_submittedAtTo-7'
        - $ref: '#/components/parameters/parameters_itemDateFrom-4'
        - $ref: '#/components/parameters/parameters_itemDateTo-4'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-11'
        - $ref: '#/components/parameters/parameters_revenueDateTo-11'
        - $ref: '#/components/parameters/parameters_labels-3'
        - $ref: '#/components/parameters/parameters_externalId'
      responses:
        '200':
          description: The partner orders report was successfully generated.
          content:
            text/csv:
              schema:
                type: string
                format: binary
                description: |
                  A CSV file containing one row per matching order.
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/reports/partner-orders/queue:
    get:
      summary: Queue an export of the partner orders report
      operationId: queuePartnerOrdersExport
      tags:
        - Reports
      description: |
        Use this endpoint to queue a background job that renders the
        partner orders report as a CSV. The job runs asynchronously and the
        resulting file is attached to the returned `QueuedJob` once it has
        finished. Pass `email=true` to additionally have the file emailed to
        the user who queued the job.

        This is the recommended variant for partners with large order
        volumes, where the synchronous
        [export](#operation/listPartnerOrders) endpoint may time out.

        Requires the `admin.sites.manage` permission.
      parameters:
        - $ref: '#/components/parameters/partnerId'
        - $ref: '#/components/parameters/parameters_siteId-54'
        - $ref: '#/components/parameters/parameters_customerId-2'
        - $ref: '#/components/parameters/parameters_status-11'
        - $ref: '#/components/parameters/parameters_query-19'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-7'
        - $ref: '#/components/parameters/parameters_submittedAtTo-7'
        - $ref: '#/components/parameters/parameters_itemDateFrom-4'
        - $ref: '#/components/parameters/parameters_itemDateTo-4'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-11'
        - $ref: '#/components/parameters/parameters_revenueDateTo-11'
        - $ref: '#/components/parameters/parameters_labels-3'
        - $ref: '#/components/parameters/parameters_externalId'
        - $ref: '#/components/parameters/parameters_email-2'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-types/{sessionTypeId}/recurrence-groups:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
  /shop/session-types/{sessionTypeId}/recurrence-groups/{recurrenceGroupId}:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
      - $ref: '#/components/parameters/recurrenceGroupId'
  /shop/session-types/{sessionTypeId}/recurrence-groups/{recurrenceGroupId}/check-update:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
      - $ref: '#/components/parameters/recurrenceGroupId'
  /shop/session-types/{sessionTypeId}/recurrence-groups/{recurrenceGroupId}/check-update/cancelled:
    parameters:
      - $ref: '#/components/parameters/parameters_sessionTypeId-2'
      - $ref: '#/components/parameters/recurrenceGroupId'
  /shop/organisations/{organisationId}/labels:
    get:
      summary: List Labels
      tags:
        - Organisations
      operationId: listOrganisationLabels
      description: |
        Returns a paginated list of every label that belongs to the
        organisation. Labels are coloured tags used to highlight or
        categorise records (customers, bookings, orders) in the admin UI.
        Use the pagination parameters to walk through large result sets.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
        - $ref: '#/components/parameters/parameters_siteIdFilter'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListOrganisationLabels'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a Label
      tags:
        - Organisations
      operationId: createOrganisationLabel
      description: |
        Create a new label against the given organisation. Labels can be
        restricted to a subset of the organisation's sites by passing the
        relevant `site_ids`; staff at other sites won't see the label in
        the admin UI.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      requestBody:
        $ref: '#/components/requestBodies/CreateOrganisationLabel'
      responses:
        '201':
          $ref: '#/components/responses/ShowOrganisationLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/labels/{labelId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_labelId'
    get:
      summary: Get a Label
      tags:
        - Organisations
      operationId: getOrganisationLabel
      description: |
        Returns the details of a single label, including its colour, the
        organisation it belongs to, and the sites it is visible to.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Label
      tags:
        - Organisations
      operationId: updateOrganisationLabel
      description: |
        Update an existing label. Pass the fields you want to change;
        `site_ids` is required and replaces the stored list of sites the
        label is visible to.
      requestBody:
        $ref: '#/components/requestBodies/UpdateOrganisationLabel'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Label
      tags:
        - Organisations
      operationId: deleteOrganisationLabel
      description: |
        Soft-delete the label. Records previously tagged with the label
        keep the historical association but the label will no longer
        appear in pickers or filters.
      responses:
        '204':
          description: The label was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/revenue-centres:
    get:
      summary: List Revenue Centres
      tags:
        - Organisations
      operationId: listOrganisationRevenueCentres
      description: |
        Returns every revenue centre defined for the organisation. The
        response includes Trybe's system revenue centres (`spa`, `deposit`,
        membership fees, ...) and any custom centres the operator has
        added. The `meta.has_custom_revenue_centres` flag indicates whether
        the organisation has overridden the Trybe defaults.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      responses:
        '200':
          $ref: '#/components/responses/ListOrganisationRevenueCentres'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a Revenue Centre
      tags:
        - Organisations
      operationId: createOrganisationRevenueCentre
      description: |
        Add a new revenue centre to the organisation. Pass at minimum a
        display `name`; `key` can be supplied if you want a stable
        identifier for use from external integrations. Adding the first
        custom centre flips `has_custom_revenue_centres` to `true` on
        subsequent list responses.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      requestBody:
        description: |
          The revenue centre to create. `name` is required; `key` defaults
          to a slugified form of `name` when omitted.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrganisationRevenueCentre'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationRevenueCentre'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/revenue-centres/{revenueCentreId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_revenueCentreId'
    get:
      summary: Get a Revenue Centre
      tags:
        - Organisations
      operationId: getOrganisationRevenueCentre
      description: |
        Returns the details of a single revenue centre, including its
        display name, default tax percentage, and whether it is a required
        Trybe revenue centre that cannot be deleted.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationRevenueCentre'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Revenue Centre
      tags:
        - Organisations
      operationId: updateOrganisationRevenueCentre
      description: |
        Update an existing revenue centre. The `name` is required; `key`
        and `tax_percent` can be supplied to change those fields. System
        revenue centres can be renamed and have their tax percentage
        updated but cannot be deleted.
      requestBody:
        description: |
          The values to update. Any field that is omitted (other than the
          required `name`) will be left unchanged.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateOrganisationRevenueCentre'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationRevenueCentre'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Revenue Centre
      tags:
        - Organisations
      operationId: deleteOrganisationRevenueCentre
      description: |
        Permanently delete the revenue centre from the organisation.
        System revenue centres (`spa`, `deposit`, membership joining fee,
        membership fee, and deposit redemption) cannot be deleted and will
        return `400 Bad Request`. Historical ledger lines that referenced
        the centre keep their reference for reporting purposes.
      responses:
        '204':
          description: The revenue centre was successfully deleted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/sales-channels:
    get:
      summary: List Sales Channels
      tags:
        - Organisations
      operationId: listSalesChannels
      description: |
        Returns a paginated list of every sales channel that belongs to the
        organisation, ordered by their stored display order then by name.
        Sales channels are used to label the source of a sale (e.g. "Front
        Desk", "Phone", "Website") so revenue can be broken down by
        channel on reports.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListSalesChannels'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a Sales Channel
      tags:
        - Organisations
      operationId: createSalesChannel
      description: |
        Create a new sales channel against the given organisation. The
        channel becomes immediately available for tagging orders,
        appointments, and other revenue-bearing records across every site
        under the organisation.
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-2'
      requestBody:
        $ref: '#/components/requestBodies/CreateSalesChannel'
      responses:
        '201':
          $ref: '#/components/responses/ShowSalesChannel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/sales-channels/{salesChannelId}:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_salesChannelId'
    get:
      summary: Get a Sales Channel
      tags:
        - Organisations
      operationId: getSalesChannel
      description: |
        Returns the details of a single sales channel, including its
        display name and the organisation it belongs to.
      responses:
        '200':
          $ref: '#/components/responses/ShowSalesChannel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Delete a Sales Channel
      tags:
        - Organisations
      operationId: deleteSalesChannel
      description: |
        Permanently delete the sales channel. Existing records that were
        previously tagged with the channel keep their historical
        association on reports, but the channel will no longer appear in
        pickers when creating new records.
      responses:
        '204':
          description: The sales channel was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/packages/{packageId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/packageId'
    get:
      summary: List availability rules for a package
      tags:
        - Packages
      operationId: listPackageAvailabilityRules
      description: |
        Returns all `AvailabilityRule`s configured on the given `Package`.
        Availability rules carve up the working calendar into windows when
        the package can or cannot be booked — useful for blocking holidays,
        restricting weekend hours, or making the package available only
        during specific seasons.

        Rule semantics: any `is_available: false` rule overrides any
        `is_available: true` rule for the same time period. Results are
        paginated.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPackageAvailabilityRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an availability rule for a package
      tags:
        - Packages
      operationId: createPackageAvailabilityRule
      description: |
        Adds a new `AvailabilityRule` to a `Package`. With
        `is_available: true` the rule opens new bookable windows; with
        `is_available: false` it blocks them. Any `false` rule overrides
        any `true` rule for the same period. Omitting date/time/weekday
        filters means the rule applies always.

        `date_from` defaults to today in the package's timezone when
        omitted. Requires the `SETTINGS_MANAGE` permission on the package's
        site.
      requestBody:
        $ref: '#/components/requestBodies/CreatePackageAvailabilityRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowPackageAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/availabilityRuleId'
    get:
      summary: Retrieve a package availability rule
      tags:
        - Packages
      operationId: getPackageAvailabilityRule
      description: |
        Returns a single `AvailabilityRule` belonging to the given
        `Package`. Requires the `SETTINGS_MANAGE` permission on the
        package's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a package availability rule
      tags:
        - Packages
      operationId: updatePackageAvailabilityRule
      description: |
        Replaces an `AvailabilityRule` on a `Package`. The server validates
        the same shape as on create, so `is_available` is required.
        Requires the `SETTINGS_MANAGE` permission on the package's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdatePackageAvailabilityRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageAvailabilityRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a package availability rule
      tags:
        - Packages
      operationId: deletePackageAvailabilityRule
      description: |
        Removes an `AvailabilityRule` from a `Package`. Calendar
        availability is recomputed from the remaining rules. Existing
        bookings are unaffected. Requires the `SETTINGS_MANAGE` permission
        on the package's site.
      responses:
        '204':
          description: Availability rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/packages/{packageId}/item-choices:
    parameters:
      - $ref: '#/components/parameters/packageId'
    get:
      summary: List item choices on a package
      tags:
        - Packages
      operationId: listPackageItemChoices
      description: |
        Returns every `PackageItemChoice` configured on the given
        `Package`. Item choices are the building blocks of a package — each
        one defines a set of options the customer picks from (e.g. "Pick a
        60-minute treatment", "Pick lunch or afternoon tea"). The package's
        overall price is the sum of the chosen options, with optional
        `option_budget` and `price_change` overrides per choice / option.

        Order is preserved across reads — it reflects the customer-facing
        order in the booking flow, and can be modified through the reorder
        endpoint on the parent package.
      responses:
        '200':
          $ref: '#/components/responses/ListPackageItemChoices'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an item choice on a package
      tags:
        - Packages
      operationId: createPackageItemChoice
      description: |
        Adds a new `PackageItemChoice` to a `Package`. The new choice is
        appended to the package's existing `item_choices` list. Every
        option's `item_type` must match the choice's `offering_type` and
        must reference an offering on the package's site that the
        authenticated user has access to.

        Server-side defaults: when `min_options` is omitted it falls back
        to `1` (or `0` if `optional: true`); when `max_options` is omitted
        it falls back to `1`. With `max_options: 1` the `option_budget` is
        ignored. Only one `hotel_room_reservation` choice is allowed per
        package — attempting to create a second returns `422`.

        Requires the `SETTINGS_MANAGE` permission on the package's site.
      requestBody:
        $ref: '#/components/requestBodies/CreatePackageItemChoice'
      responses:
        '201':
          $ref: '#/components/responses/ShowPackageItemChoice'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/item-choices/{itemChoiceId}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/itemChoiceId'
    get:
      summary: Retrieve a package item choice
      tags:
        - Packages
      operationId: getPackageItemChoice
      description: |
        Returns a single `PackageItemChoice` belonging to the given
        `Package`, including the full option list and any configured
        start-time rules.
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageItemChoice'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a package item choice
      tags:
        - Packages
      operationId: updatePackageItemChoice
      description: |
        Updates a `PackageItemChoice` on a `Package`. Every field is
        optional; only the fields you send are written. Update is the only
        place where `start_time_rules`, `allow_overlaps` and
        `choice_configuration` can be set.

        Setting `visible: false` is only valid when `offering_type` is
        `product`; other types return `400`. When `max_options` becomes `1`
        any `option_budget` is dropped server-side. When the parent
        package's `prevent_choice_overlaps` is not true, `allow_overlaps`
        is forced to `null`.

        Requires the `SETTINGS_MANAGE` permission on the package's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdatePackageItemChoice'
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageItemChoice'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a package item choice
      tags:
        - Packages
      operationId: deletePackageItemChoice
      description: |
        Removes a `PackageItemChoice` from a `Package`. The remaining
        choices keep their order. Existing bookings of the package are
        unaffected. Requires the `SETTINGS_MANAGE` permission on the
        package's site.
      responses:
        '204':
          description: Item choice deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/packages/{packageId}/price-rules:
    parameters:
      - $ref: '#/components/parameters/packageId'
    get:
      summary: List price rules for a package
      tags:
        - Packages
      operationId: listPackagePriceRules
      description: |
        Returns all `PriceRule`s configured on the given `Package`. Price
        rules determine the price the customer pays based on when the
        package is booked — peak vs off-peak, weekday vs weekend, seasonal
        overrides. The first rule whose conditions match the booking wins;
        when no rule matches, the package falls back to a sensible default.

        Results are paginated. Requires read access to the package's site.
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListPackagePriceRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a price rule for a package
      tags:
        - Packages
      operationId: createPackagePriceRule
      description: |
        Adds a new `PriceRule` to a `Package`. Combine date ranges, time
        windows and weekday filters to express most pricing scenarios —
        peak vs off-peak, weekday vs weekend, seasonal overrides. The first
        rule whose conditions match a given booking wins. Sending no
        filters creates a fallback "always applies" rule.

        `date_from` defaults to today in the site's timezone when omitted. When
        `offering_standard_price` is enabled for the site, the package's
        `standard_price` must be set before a price rule can be created. A zero
        amount counts as set. Requires the `SETTINGS_MANAGE` permission on the
        package's site.
      requestBody:
        $ref: '#/components/requestBodies/CreatePackagePriceRule'
      responses:
        '201':
          $ref: '#/components/responses/ShowPackagePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/price-rules/{priceRuleId}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/priceRuleId'
    get:
      summary: Retrieve a package price rule
      tags:
        - Packages
      operationId: getPackagePriceRule
      description: |
        Returns a single `PriceRule` belonging to the given `Package`.
        Requires read access to the package's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowPackagePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a package price rule
      tags:
        - Packages
      operationId: updatePackagePriceRule
      description: |
        Replaces a `PriceRule` on a `Package`. The server validates the same
        shape as on create, so `price` is required. When
        `offering_standard_price` is enabled for the site, the package's
        `standard_price` must be set before a price rule can be updated. A zero
        amount counts as set. Requires the `SETTINGS_MANAGE` permission on the
        package's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdatePackagePriceRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowPackagePriceRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a package price rule
      tags:
        - Packages
      operationId: deletePackagePriceRule
      description: |
        Removes a `PriceRule` from a `Package`. Existing bookings priced
        under this rule are unaffected — they retain the price recorded at
        booking time. When `offering_standard_price` is enabled for the site, the
        package's `standard_price` must be set before a price rule can be deleted.
        A zero amount counts as set. Requires the `SETTINGS_MANAGE` permission on
        the package's site.
      responses:
        '204':
          description: Price rule deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/reports/bookable-area-occupancy:
    get:
      summary: Bookable area occupancy report
      operationId: listBookableAreaOccupancy
      tags:
        - Reports
      description: |
        For each bookable area at the requested site, returns bookable / blocked / booked
        minutes across the requested date range. Capped to 60 days per request — for larger
        ranges, queue an export with
        [`/shop/reports/bookable-area-occupancy/queue`](/endpoints/Reports#queueBookableAreaOccupancyExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-55'
        - $ref: '#/components/parameters/parameters_dateFrom-5'
        - $ref: '#/components/parameters/parameters_dateTo-5'
        - $ref: '#/components/parameters/bookableAreaIds'
        - $ref: '#/components/parameters/parameters_zoneId-7'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookableAreaOccupancyResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/bookable-area-occupancy/queue:
    get:
      summary: Queue an export of the bookable area occupancy report
      operationId: queueBookableAreaOccupancyExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the bookable area occupancy report to be generated
        asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-55'
        - $ref: '#/components/parameters/parameters_dateFrom-5'
        - $ref: '#/components/parameters/parameters_dateTo-5'
        - $ref: '#/components/parameters/bookableAreaIds'
        - $ref: '#/components/parameters/parameters_zoneId-7'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/cancellations-and-no-shows:
    get:
      summary: Cancellations and no-shows report
      operationId: listCancellationsAndNoShows
      tags:
        - Reports
      description: |
        Summarises baskets that were cancelled or marked as a no-show in the given revenue date
        range. The response is a display-ready table (rows of header + body cells) split into
        `data` (one row per status) and `totals` (a single combined row). The response can also
        be requested as a CSV by sending `Accept: text/csv`.

        For programmatic access to the same numbers in JSON-native shape, use
        [`/shop/reports/cancellations-and-no-shows-v2`](/endpoints/Reports#listCancellationsAndNoShowsV2).
        For large date ranges or background email-delivered exports, queue the report with
        [`/shop/reports/cancellations-and-no-shows/queue`](/endpoints/Reports#queueCancellationsAndNoShowsExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-56'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-12'
        - $ref: '#/components/parameters/parameters_revenueDateTo-12'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancellationsAndNoShowsResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/cancellations-and-no-shows-v2:
    get:
      summary: Cancellations and no-shows report (v2)
      operationId: listCancellationsAndNoShowsV2
      tags:
        - Reports
      description: |
        Returns the cancellations and no-shows totals as a JSON-native object — one bucket each
        for cancelled baskets, no-show baskets, and a combined total. Money fields are integers
        in the site's minor units (e.g. pence for GBP).

        Prefer this endpoint over [`/shop/reports/cancellations-and-no-shows`](/endpoints/Reports#listCancellationsAndNoShows)
        when integrating with a system rather than rendering a table.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-56'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-12'
        - $ref: '#/components/parameters/parameters_revenueDateTo-12'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancellationsAndNoShowsV2Response'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/cancellations-and-no-shows/queue:
    get:
      summary: Queue an export of the cancellations and no-shows report
      operationId: queueCancellationsAndNoShowsExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the cancellations and no-shows report so it can be generated
        asynchronously. The report is run on a background worker and, when `email=true`, is
        delivered to the calling user once ready. Use this instead of the synchronous endpoint
        when the date range spans more than a few months.

        See [`/shop/reports/cancellations-and-no-shows`](/endpoints/Reports#listCancellationsAndNoShows)
        for the synchronous variant.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-56'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-12'
        - $ref: '#/components/parameters/parameters_revenueDateTo-12'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/charge-list:
    get:
      summary: Charges list
      operationId: listCharges
      tags:
        - Reports
      description: |
        A paginated list of individual charges (payments and refunds) at the requested site,
        filterable by status, processor, completion date, revenue date, payout date, and more.
        A per-processor net total is returned alongside the page of data so dashboards can show
        a running total without needing to fetch every page.

        For large date ranges or background CSV delivery, use
        [`/shop/reports/charge-list/queue`](/endpoints/Reports#queueChargeListExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-57'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/completedFrom'
        - $ref: '#/components/parameters/completedTo'
        - $ref: '#/components/parameters/createdFrom'
        - $ref: '#/components/parameters/createdTo'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-13'
        - $ref: '#/components/parameters/parameters_revenueDateTo-13'
        - $ref: '#/components/parameters/payoutDateFrom'
        - $ref: '#/components/parameters/payoutDateTo'
        - $ref: '#/components/parameters/parameters_status-12'
        - $ref: '#/components/parameters/chargeableType'
        - $ref: '#/components/parameters/chargeType'
        - $ref: '#/components/parameters/parameters_processor'
        - $ref: '#/components/parameters/detailsSource'
        - $ref: '#/components/parameters/parameters_orderStatus-2'
        - $ref: '#/components/parameters/createdBy'
      responses:
        '200':
          description: The charges were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChargeListResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/charge-list/queue:
    get:
      summary: Queue an export of the charges list
      operationId: queueChargeListExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the charges list to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-57'
        - $ref: '#/components/parameters/completedFrom'
        - $ref: '#/components/parameters/completedTo'
        - $ref: '#/components/parameters/createdFrom'
        - $ref: '#/components/parameters/createdTo'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-13'
        - $ref: '#/components/parameters/parameters_revenueDateTo-13'
        - $ref: '#/components/parameters/payoutDateFrom'
        - $ref: '#/components/parameters/payoutDateTo'
        - $ref: '#/components/parameters/parameters_status-12'
        - $ref: '#/components/parameters/chargeableType'
        - $ref: '#/components/parameters/chargeType'
        - $ref: '#/components/parameters/parameters_processor'
        - $ref: '#/components/parameters/detailsSource'
        - $ref: '#/components/parameters/parameters_orderStatus-2'
        - $ref: '#/components/parameters/createdBy'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/commission:
    get:
      summary: Commission report
      operationId: listCommission
      tags:
        - Reports
      description: |
        Returns the commission earned by each practitioner at the requested site for the given
        period, broken down by commission package. Money fields are decimal strings in the
        site's currency (rather than minor-unit integers) to preserve the precision of the
        underlying commission calculation.

        For background CSV delivery use
        [`/shop/reports/commission/queue`](/endpoints/Reports#queueCommissionExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-58'
        - $ref: '#/components/parameters/parameters_dateFrom-6'
        - $ref: '#/components/parameters/parameters_dateTo-6'
        - $ref: '#/components/parameters/earnerId'
        - $ref: '#/components/parameters/earnerType'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommissionReportResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/commission/queue:
    get:
      summary: Queue an export of the commission report
      operationId: queueCommissionExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the commission report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-58'
        - $ref: '#/components/parameters/parameters_dateFrom-6'
        - $ref: '#/components/parameters/parameters_dateTo-6'
        - $ref: '#/components/parameters/earnerId'
        - $ref: '#/components/parameters/earnerType'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/commission-breakdown:
    get:
      summary: Commission breakdown report
      operationId: listCommissionBreakdown
      tags:
        - Reports
      description: |
        Returns a paginated, item-level breakdown of commission earned by practitioners
        at the requested site for the given period. Each row represents a single sold
        item and includes the offering, the commission rate applied, and the resulting
        commission and surcharge amounts. Money fields are decimal strings in the site's
        currency (rather than minor-unit integers) to preserve the precision of the
        underlying commission calculation.

        For background CSV delivery use
        [`/shop/reports/commission-breakdown/queue`](/endpoints/Reports#queueCommissionBreakdownExport).
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/parameters_dateFrom-7'
        - $ref: '#/components/parameters/parameters_dateTo-7'
        - $ref: '#/components/parameters/parameters_practitionerId-9'
        - $ref: '#/components/parameters/earnerId'
        - $ref: '#/components/parameters/earnerType'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommissionBreakdownResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/commission-breakdown/queue:
    get:
      summary: Queue an export of the commission breakdown report
      operationId: queueCommissionBreakdownExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the commission breakdown report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/parameters_dateFrom-7'
        - $ref: '#/components/parameters/parameters_dateTo-7'
        - $ref: '#/components/parameters/parameters_practitionerId-9'
        - $ref: '#/components/parameters/earnerId'
        - $ref: '#/components/parameters/earnerType'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/daily-revenue-stats:
    get:
      summary: Daily revenue stats
      operationId: getDailyRevenueStats
      tags:
        - Reports
      description: |
        The dashboard payload that powers the "today at a glance" revenue view for a single
        site. Returns revenue by centre, payments by processor, top items, and other
        operational counts. Defaults to today in the site's timezone if `date` is omitted.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-59'
        - $ref: '#/components/parameters/parameters_date-13'
      responses:
        '200':
          description: The stats were successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DailyRevenueStatsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/daily-sales-stats:
    get:
      summary: Daily sales stats
      operationId: getDailySalesStats
      tags:
        - Reports
      description: |
        The dashboard payload that powers the "today's sales" view for a single site. Returns
        payments grouped by processor, refunds, the day's orders, aggregate order stats, and
        membership sales. Defaults to today in the site's timezone if `date` is omitted.

        Companion endpoint to
        [`/shop/reports/daily-revenue-stats`](/endpoints/Reports#getDailyRevenueStats).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-59'
        - $ref: '#/components/parameters/parameters_date-13'
      responses:
        '200':
          description: The stats were successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DailySalesStatsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/day-charges:
    get:
      summary: Charges completed on a single day
      operationId: listDayCharges
      tags:
        - Reports
      description: |
        A convenience wrapper around [`/shop/reports/charge-list`](/endpoints/Reports#listCharges)
        pre-filtered to a single day. Returns charges (payments and refunds) completed on the
        given date, paginated 100 to a page, alongside the per-processor totals for the day.
        Intended for end-of-day reconciliation views.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-60'
        - $ref: '#/components/parameters/parameters_date-14'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          description: The day's charges were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChargeListResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/discount-usage:
    get:
      summary: Discount usage report
      operationId: listDiscountUsage
      tags:
        - DiscountUsage
      description: |
        Display-formatted table of how each discount type has been used across orders in the
        filter range. For JSON-native consumption use
        [`/shop/reports/discount-usage-v2`](/endpoints/DiscountUsage#listDiscountUsageV2);
        for large exports use
        [`/shop/reports/discount-usage/queue`](/endpoints/DiscountUsage#queueDiscountUsageExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-61'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-14'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TableReport'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/discount-usage-v2:
    get:
      summary: Discount usage report (v2)
      operationId: listDiscountUsageV2
      tags:
        - DiscountUsage
      description: |
        Returns discount usage as a JSON-native list: one row per discount type, with counts
        and total amounts (in minor units) for baskets, items, and the combined total.

        Prefer this endpoint over [`/shop/reports/discount-usage`](/endpoints/DiscountUsage#listDiscountUsage)
        when integrating with another system.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-61'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-14'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DiscountUsageV2Response'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/discount-usage/queue:
    get:
      summary: Queue an export of the discount usage report
      operationId: queueDiscountUsageExport
      tags:
        - DiscountUsage
      description: |
        Queues a CSV export of the discount usage report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-61'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-14'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/general-ledger:
    get:
      summary: General ledger
      operationId: listGeneralLedger
      tags:
        - Reports
      description: |
        A chronologically-sorted ledger of every revenue, payment, refund and revenue-reversal
        event at a site over the requested period. Use this for end-to-end financial
        reconciliation; for voucher-specific reconciliation see
        [`/shop/reports/voucher-ledger-detailed`](/endpoints/VoucherLedger#listVoucherLedgerDetailed).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-62'
        - $ref: '#/components/parameters/parameters_dateFrom-8'
        - $ref: '#/components/parameters/parameters_dateTo-8'
      responses:
        '200':
          description: The ledger was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneralLedgerResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/item-revenues:
    get:
      summary: Item revenues report
      operationId: listItemRevenues
      tags:
        - Reports
      description: |
        Paginated list of submitted/settled basket items annotated with their per-revenue-centre
        allocations. Useful for reconciling revenue by offering, by revenue centre, or by item
        date. Money fields are integers in minor units.

        For large date ranges or background CSV delivery use
        [`/shop/reports/item-revenues/queue`](/endpoints/Reports#queueItemRevenuesExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-63'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-15'
        - $ref: '#/components/parameters/parameters_revenueDateTo-15'
        - $ref: '#/components/parameters/parameters_itemDateFrom-5'
        - $ref: '#/components/parameters/parameters_itemDateTo-5'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtFrom-3'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtTo-3'
        - $ref: '#/components/parameters/parameters_offeringType-6'
        - $ref: '#/components/parameters/parameters_offeringIds'
        - $ref: '#/components/parameters/parameters_revenueCentres'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ItemRevenuesResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/item-revenues/queue:
    get:
      summary: Queue an export of the item revenues report
      operationId: queueItemRevenuesExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the item revenues report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-63'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-15'
        - $ref: '#/components/parameters/parameters_revenueDateTo-15'
        - $ref: '#/components/parameters/parameters_itemDateFrom-5'
        - $ref: '#/components/parameters/parameters_itemDateTo-5'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtFrom-3'
        - $ref: '#/components/parameters/parameters_orderSubmittedAtTo-3'
        - $ref: '#/components/parameters/parameters_offeringType-6'
        - $ref: '#/components/parameters/parameters_offeringIds'
        - $ref: '#/components/parameters/parameters_revenueCentres'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/occupancy-overview:
    get:
      summary: Occupancy overview
      operationId: listOccupancyOverview
      tags:
        - Reports
      description: |
        A daily occupancy roll-up for a site, combining booked-basket counts, session counts
        and capacity, blocked-time minutes, and the same per-day numbers reported by the
        practitioner and room occupancy reports. Intended to power a single-screen overview of
        "how busy is this site this week". Capped to 7 days per request.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-64'
        - $ref: '#/components/parameters/parameters_dateFrom-9'
        - $ref: '#/components/parameters/parameters_dateTo-9'
        - $ref: '#/components/parameters/parameters_zoneId-8'
      responses:
        '200':
          description: The overview was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OccupancyOverviewResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/pay-by-link-payments:
    get:
      summary: Pay-by-link payments list
      operationId: listPayByLinkPayments
      tags:
        - Reports
      description: |
        A paginated list of pay-by-link charges issued at the given site. Useful for tracking
        outstanding payment links sent to customers (`status=pending`) and reviewing recently
        collected pay-by-link payments.

        For the smart-filter options used to power list-page chips and saved searches, see
        [`/shop/reports/pay-by-link-payments/smart-filters`](/endpoints/Reports#listPayByLinkPaymentsSmartFilters).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-65'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPage'
        - $ref: '#/components/parameters/parameters_createdFrom'
        - $ref: '#/components/parameters/parameters_createdTo'
        - $ref: '#/components/parameters/parameters_completedFrom'
        - $ref: '#/components/parameters/parameters_completedTo'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-16'
        - $ref: '#/components/parameters/parameters_revenueDateTo-16'
        - $ref: '#/components/parameters/parameters_status-13'
        - $ref: '#/components/parameters/parameters_sort-5'
        - $ref: '#/components/parameters/parameters_sortOrder-2'
      responses:
        '200':
          description: The pay-by-link payments were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PayByLinkPaymentsResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/pay-by-link-payments/smart-filters:
    get:
      summary: Smart filters for the pay-by-link payments list
      operationId: listPayByLinkPaymentsSmartFilters
      tags:
        - Reports
      description: |
        Returns the smart-filter options that can be used to filter the pay-by-link payments
        list — e.g. "outstanding for over 7 days", "completed today". Companion endpoint to
        [`/shop/reports/pay-by-link-payments`](/endpoints/Reports#listPayByLinkPayments).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-65'
      responses:
        '200':
          $ref: '#/components/responses/SmartFiltersResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/payouts/{payoutId}/queue:
    get:
      summary: Queue a CSV export of a single payout
      operationId: queuePayoutExport
      tags:
        - Reports
      description: |
        Queues an asynchronous CSV export of every charge included in the given payout. Used to
        produce the per-payout transaction listing that finance teams reconcile against the
        deposit appearing in the merchant's bank account.
      parameters:
        - $ref: '#/components/parameters/payoutId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/practitioner-utilisation:
    get:
      summary: Practitioner utilisation report
      operationId: listPractitionerUtilisation
      tags:
        - Reports
      description: |
        For each practitioner working at the given site, returns bookable / booked / blocked
        minutes and attributed net revenue across the requested date range. Capped to 31 days
        per request — for larger ranges, queue an export with
        [`/shop/reports/practitioner-utilisation/queue`](/endpoints/Reports#queuePractitionerUtilisationExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-66'
        - $ref: '#/components/parameters/parameters_dateFrom-10'
        - $ref: '#/components/parameters/parameters_dateTo-10'
        - $ref: '#/components/parameters/parameters_zoneId-9'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PractitionerUtilisationResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/practitioner-utilisation/queue:
    get:
      summary: Queue an export of the practitioner utilisation report
      operationId: queuePractitionerUtilisationExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the practitioner utilisation report. Use this in preference to
        the synchronous endpoint when the report needs to be delivered to multiple recipients
        or when the calling context cannot wait for the synchronous response.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-66'
        - $ref: '#/components/parameters/parameters_dateFrom-10'
        - $ref: '#/components/parameters/parameters_dateTo-10'
        - $ref: '#/components/parameters/parameters_zoneId-9'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-centre:
    get:
      summary: Revenue by centre report (v1)
      operationId: listRevenueByCentre
      tags:
        - RevenueByCentre
      description: |
        Display-formatted version of the revenue by centre summary, returning two
        [`TableReport`](#/components/schemas/TableReport) blocks: `data` (one row per day) and
        `totals` (the combined totals row).

        Prefer [`/shop/reports/revenue-by-centre-v2`](/endpoints/RevenueByCentre#listRevenueByCentreSummary)
        for programmatic / JSON consumption. For large date ranges or background CSV delivery
        use [`/shop/reports/revenue-by-centre/queue`](/endpoints/RevenueByCentre#queueRevenueByCentreExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-45'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-9'
        - $ref: '#/components/parameters/parameters_revenueDateTo-9'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                type: object
                title: RevenueByCentreV1Response
                additionalProperties: false
                required:
                  - data
                  - totals
                properties:
                  data:
                    $ref: '#/components/schemas/TableReport'
                  totals:
                    $ref: '#/components/schemas/TableReport'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-centre/queue:
    get:
      summary: Queue an export of the revenue by centre report (v1)
      operationId: queueRevenueByCentreExport
      tags:
        - RevenueByCentre
      description: |
        Queues a CSV export of the v1 revenue by centre report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-45'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-9'
        - $ref: '#/components/parameters/parameters_revenueDateTo-9'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-order-label:
    get:
      summary: Revenue by order label report
      operationId: listRevenueByOrderLabel
      tags:
        - Reports
      description: |
        Summarises submitted/settled basket revenue grouped by order label. The response is
        a display-ready table (header + body rows). For JSON-native consumption use
        [`/shop/reports/revenue-by-order-label-v2`](/endpoints/Reports#listRevenueByOrderLabelV2);
        for large date ranges export asynchronously via
        [`/shop/reports/revenue-by-order-label/queue`](/endpoints/Reports#queueRevenueByOrderLabelExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-12'
        - $ref: '#/components/parameters/parameters_revenueDateTo-12'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TableReport'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-order-label-v2:
    get:
      summary: Revenue by order label report (v2)
      operationId: listRevenueByOrderLabelV2
      tags:
        - Reports
      description: |
        Returns submitted/settled basket revenue grouped by order label, in a JSON-native shape
        suitable for programmatic consumption. Each entry also includes a per-revenue-centre
        breakdown. All money fields are integers in minor units.

        For the legacy display-formatted variant see
        [`/shop/reports/revenue-by-order-label`](/endpoints/Reports#listRevenueByOrderLabel).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-14'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_itemDateFrom-6'
        - $ref: '#/components/parameters/parameters_itemDateTo-6'
        - $ref: '#/components/parameters/parameters_labels-4'
        - $ref: '#/components/parameters/parameters_revenueCentre-3'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevenueByOrderLabelV2Response'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-order-label/queue:
    get:
      summary: Queue an export of the revenue by order label report
      operationId: queueRevenueByOrderLabelExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the revenue by order label report. Use this in preference to the
        synchronous endpoint when the date range spans more than a few months.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-12'
        - $ref: '#/components/parameters/parameters_revenueDateTo-12'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-sales-channel:
    get:
      summary: Revenue by sales channel report
      operationId: listRevenueBySalesChannel
      tags:
        - Reports
      description: |
        Breaks down submitted and settled basket revenue by sales channel — useful for
        attributing income to the originating booking journey (website widget, in-spa POS,
        partner integration, etc.). Each entry also returns a per-revenue-centre split so the
        same totals can be sliced further.

        For exports over very large date ranges, queue a CSV with
        [`/shop/reports/revenue-by-sales-channel/queue`](/endpoints/Reports#queueRevenueBySalesChannelExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-14'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
        - $ref: '#/components/parameters/parameters_itemDateFrom-6'
        - $ref: '#/components/parameters/parameters_itemDateTo-6'
        - $ref: '#/components/parameters/parameters_salesChannel-2'
        - $ref: '#/components/parameters/parameters_revenueCentre-4'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevenueBySalesChannelResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-by-sales-channel/queue:
    get:
      summary: Queue an export of the revenue by sales channel report
      operationId: queueRevenueBySalesChannelExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the revenue by sales channel report to be generated
        asynchronously. Prefer this endpoint over the synchronous variant for date ranges
        that span more than a couple of months — for shorter ranges, see
        [`/shop/reports/revenue-by-sales-channel`](/endpoints/Reports#listRevenueBySalesChannel).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-14'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
        - $ref: '#/components/parameters/parameters_itemDateFrom-6'
        - $ref: '#/components/parameters/parameters_itemDateTo-6'
        - $ref: '#/components/parameters/parameters_salesChannel-2'
        - $ref: '#/components/parameters/parameters_revenueCentre-4'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-projection:
    get:
      summary: Revenue projection report
      operationId: listRevenueProjection
      tags:
        - Reports
      description: |
        Projects expected revenue across a date range of up to 31 days, broken down by offering
        and revenue centre. Useful for daily/weekly dashboards that need to look ahead at booked
        revenue. Money fields are integers in minor units.

        For background CSV export — including delivery by email — see
        [`/shop/reports/revenue-projection/queue`](/endpoints/Reports#queueRevenueProjectionExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-68'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-17'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_itemDateFrom-6'
        - $ref: '#/components/parameters/parameters_itemDateTo-6'
      responses:
        '200':
          description: The projection was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevenueProjectionResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/revenue-projection/queue:
    get:
      summary: Queue an export of the revenue projection report
      operationId: queueRevenueProjectionExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the revenue projection report, generated asynchronously on a
        background worker. The same 31-day maximum range applies as for the synchronous
        endpoint.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-68'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-17'
        - $ref: '#/components/parameters/parameters_revenueDateTo-14'
        - $ref: '#/components/parameters/parameters_itemDateFrom-6'
        - $ref: '#/components/parameters/parameters_itemDateTo-6'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/room-occupancy:
    get:
      summary: Room occupancy report
      operationId: listRoomOccupancy
      tags:
        - Reports
      description: |
        For each room at the requested site, returns bookable / appointment / session / blocked
        minutes across the requested date range. Capped to 60 days per request — for larger
        ranges, queue an export with
        [`/shop/reports/room-occupancy/queue`](/endpoints/Reports#queueRoomOccupancyExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-55'
        - $ref: '#/components/parameters/parameters_dateFrom-5'
        - $ref: '#/components/parameters/parameters_dateTo-5'
        - $ref: '#/components/parameters/parameters_roomIds'
        - $ref: '#/components/parameters/parameters_zoneId-10'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoomOccupancyResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/room-occupancy/queue:
    get:
      summary: Queue an export of the room occupancy report
      operationId: queueRoomOccupancyExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the room occupancy report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-55'
        - $ref: '#/components/parameters/parameters_dateFrom-5'
        - $ref: '#/components/parameters/parameters_dateTo-5'
        - $ref: '#/components/parameters/parameters_roomIds'
        - $ref: '#/components/parameters/parameters_zoneId-10'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/run-sheet:
    get:
      summary: Run sheet for a single day
      operationId: listRunSheet
      tags:
        - Reports
      description: |
        Returns the chronological list of appointments and sessions taking place at a site on a
        single day — the operational "run sheet" used by front-of-house staff to walk through
        the day. Optionally filter to one or more practitioners. CSV output is available via
        `Accept: text/csv`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-69'
        - $ref: '#/components/parameters/parameters_date-15'
        - $ref: '#/components/parameters/parameters_practitionerId-10'
      responses:
        '200':
          description: The run sheet was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RunSheetResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/top-customers:
    get:
      summary: Top customers report
      operationId: listTopCustomers
      tags:
        - Reports
      description: |
        Returns the top 100 customers by net total across the filter range, sorted by net total
        descending. The customer name returned is the one most frequently used on the orders
        matched — the source-of-truth customer record lives in the [Customers API](/endpoints/Customers).

        For large date ranges or background CSV delivery, queue an export with
        [`/shop/reports/top-customers/queue`](/endpoints/Reports#queueTopCustomersExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-18'
        - $ref: '#/components/parameters/parameters_revenueDateTo-17'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopCustomersResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/top-customers/queue:
    get:
      summary: Queue an export of the top customers report
      operationId: queueTopCustomersExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the top customers report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-67'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-18'
        - $ref: '#/components/parameters/parameters_revenueDateTo-17'
        - $ref: '#/components/parameters/parameters_submittedAtFrom-8'
        - $ref: '#/components/parameters/parameters_submittedAtTo-8'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/top-offerings:
    get:
      summary: Top offerings report
      operationId: listTopOfferings
      tags:
        - Reports
      description: |
        Returns the top-selling offerings (appointments, sessions, products, packages, etc.)
        across the filter range, alongside per-offering-type roll-up totals. Useful for
        headline "what's our best seller" dashboards.

        For background CSV delivery, use
        [`/shop/reports/top-offerings/queue`](/endpoints/Reports#queueTopOfferingsExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-70'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-19'
        - $ref: '#/components/parameters/parameters_revenueDateTo-18'
        - $ref: '#/components/parameters/parameters_itemDateFrom-5'
        - $ref: '#/components/parameters/parameters_itemDateTo-5'
        - $ref: '#/components/parameters/parameters_offeringType-7'
        - $ref: '#/components/parameters/parameters_offeringIds'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopOfferingsResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/top-offerings/queue:
    get:
      summary: Queue an export of the top offerings report
      operationId: queueTopOfferingsExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the top offerings report to be generated asynchronously.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-70'
        - $ref: '#/components/parameters/parameters_revenueDateFrom-19'
        - $ref: '#/components/parameters/parameters_revenueDateTo-18'
        - $ref: '#/components/parameters/parameters_itemDateFrom-5'
        - $ref: '#/components/parameters/parameters_itemDateTo-5'
        - $ref: '#/components/parameters/parameters_offeringType-7'
        - $ref: '#/components/parameters/parameters_offeringIds'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/trybe-payments-balance:
    get:
      summary: Trybe Payments balance report
      operationId: listTrybePaymentsBalance
      tags:
        - Reports
      description: |
        A running ledger of Trybe Payments (Adyen balance platform) transfers — payments,
        refunds, and payouts — for the given site over the requested date range. Use this to
        reconcile the merchant's balance held with Trybe Payments. Defaults to the current
        calendar month if `date_from` / `date_to` are omitted.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-71'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          description: The balance report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrybePaymentsBalanceResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/voucher-codes:
    get:
      summary: Voucher codes report
      operationId: listVoucherCodesReport
      tags:
        - Reports
      description: |
        A paginated list of voucher codes issued at the given site, with filtering by status,
        code, face amount, balance, expiry date and creation date. Money values are integers in
        minor units. For large exports, use
        [`/shop/reports/voucher-codes/queue`](/endpoints/Reports#queueVoucherCodesExport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-72'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/parameters_perPage'
        - $ref: '#/components/parameters/parameters_code-4'
        - $ref: '#/components/parameters/parameters_status-14'
        - $ref: '#/components/parameters/parameters_amount'
        - $ref: '#/components/parameters/parameters_balance'
        - $ref: '#/components/parameters/parameters_voucherTypeId-2'
        - $ref: '#/components/parameters/parameters_fulfillmentStatus'
        - $ref: '#/components/parameters/parameters_createdSince'
        - $ref: '#/components/parameters/parameters_expiredRangeFrom'
        - $ref: '#/components/parameters/parameters_expiredRangeTo'
      responses:
        '200':
          description: The voucher codes were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VoucherCodesResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/voucher-codes/queue:
    get:
      summary: Queue an export of the voucher codes report
      operationId: queueVoucherCodesExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the voucher codes report to be generated asynchronously. Use
        this in preference to the synchronous endpoint when issuing a large number of codes.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-72'
        - $ref: '#/components/parameters/parameters_code-4'
        - $ref: '#/components/parameters/parameters_status-14'
        - $ref: '#/components/parameters/parameters_amount'
        - $ref: '#/components/parameters/parameters_balance'
        - $ref: '#/components/parameters/parameters_voucherTypeId-2'
        - $ref: '#/components/parameters/parameters_fulfillmentStatus'
        - $ref: '#/components/parameters/parameters_createdSince'
        - $ref: '#/components/parameters/parameters_expiredRangeFrom'
        - $ref: '#/components/parameters/parameters_expiredRangeTo'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/voucher-ledger-detailed:
    get:
      summary: Voucher ledger detailed
      operationId: listVoucherLedgerDetailed
      tags:
        - VoucherLedger
      description: |
        Returns a chronological line-by-line ledger of voucher sales, redemptions, and refunds
        in the requested period at a site. Each entry is annotated with the order, basket item,
        payment, voucher code, and (where relevant) refund it relates to so it can be linked
        back to the underlying records.

        For a single-line aggregate of the same period, see
        [`/shop/reports/voucher-ledger-summary`](/endpoints/VoucherLedger#getVoucherLedgerSummaryReport).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-62'
        - $ref: '#/components/parameters/parameters_dateFrom-8'
        - $ref: '#/components/parameters/parameters_dateTo-8'
      responses:
        '200':
          description: The ledger was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VoucherLedgerDetailedResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/voucher-ledger-summary:
    get:
      summary: Voucher ledger summary
      operationId: getVoucherLedgerSummaryReport
      tags:
        - VoucherLedger
      description: |
        Returns a single-line summary of voucher sales, redemptions, and the resulting opening
        and closing voucher liability balances for the given period at a site. Use this to
        reconcile the deferred-revenue balance held against Trybe-issued vouchers. For a
        line-by-line breakdown, see
        [`/shop/reports/voucher-ledger-detailed`](/endpoints/VoucherLedger#listVoucherLedgerDetailed).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-62'
        - $ref: '#/components/parameters/parameters_dateFrom-8'
        - $ref: '#/components/parameters/parameters_dateTo-8'
      responses:
        '200':
          description: The summary was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VoucherLedgerSummaryResponseDate'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/reports/yielded-sales:
    get:
      summary: Yielded sales report
      operationId: listYieldedSales
      tags:
        - Reports
      description: |
        Paginated list of every sale where a yield rule moved the price — up at
        peak, or down to fill quiet spells. Sales made when no rule applied
        (the implicit standard tier) are not included.

        Each row is a snapshot taken at the time of sale: the rule, tier, fill
        rate, and baseline price are read from provenance stored when the price
        was resolved, never recomputed from the current rule or price
        configuration. Editing, renaming, or deleting a rule after a sale does
        not change how that sale reports.

        Money fields are integers in the minor units of each row's `currency`.
        Totals are grouped per currency and are never summed across currencies.
        Rows whose `status` is `refunded` or `cancelled` stay in the list,
        flagged, but are excluded from the revenue and net-uplift totals so the
        numbers reconcile with other sales reports.

        Results default to most recent sale first, tiebroken on `id` so
        ordering is stable when sales share a timestamp. The response also
        includes a CSV variant when requesting with `Accept: text/csv`; for
        large date ranges or background delivery use
        [`/shop/reports/yielded-sales/queue`](/endpoints/Reports#queueYieldedSalesExport).

        Requires the `reports.view` permission (`reports.download` for the CSV
        variant). Sites without the `advanced_yield_management` feature
        respond `404`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-73'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_dateFrom-11'
        - $ref: '#/components/parameters/parameters_dateTo-11'
        - $ref: '#/components/parameters/search'
        - $ref: '#/components/parameters/parameters_offeringIds-2'
        - $ref: '#/components/parameters/parameters_offeringTypes'
        - $ref: '#/components/parameters/yieldRuleIds'
        - $ref: '#/components/parameters/tiers'
      responses:
        '200':
          description: The report was successfully generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YieldedSalesReportResponse'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/reports/yielded-sales/queue:
    get:
      summary: Queue an export of the yielded sales report
      operationId: queueYieldedSalesExport
      tags:
        - Reports
      description: |
        Queues a CSV export of the yielded sales report to be generated
        asynchronously. Use this instead of the synchronous `text/csv` variant
        of [`/shop/reports/yielded-sales`](/endpoints/Reports#listYieldedSales)
        for large date ranges. Requires the `reports.download` permission.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-73'
        - $ref: '#/components/parameters/parameters_dateFrom-11'
        - $ref: '#/components/parameters/parameters_dateTo-11'
        - $ref: '#/components/parameters/search'
        - $ref: '#/components/parameters/parameters_offeringIds-2'
        - $ref: '#/components/parameters/parameters_offeringTypes'
        - $ref: '#/components/parameters/yieldRuleIds'
        - $ref: '#/components/parameters/tiers'
        - $ref: '#/components/parameters/parameters_email-3'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/blocked-time-presets:
    get:
      summary: List blocked-time presets
      operationId: listBlockedTimePresets
      tags:
        - BlockedTimePresets
      description: |
        Returns a paginated list of `BlockedTimePreset`s at the given
        site, alphabetised by name. Use this to populate the preset
        picker in the operator calendar UI.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListBlockedTimePresets'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a blocked-time preset
      operationId: createBlockedTimePreset
      tags:
        - BlockedTimePresets
      description: |
        Creates a new `BlockedTimePreset` at the given site. Only `name`
        is required; the remaining fields configure the defaults that
        pre-fill a `BlockedTime` created from this preset.

        Requires the `SETTINGS_MANAGE` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      requestBody:
        $ref: '#/components/requestBodies/CreateBlockedTimePreset'
      responses:
        '201':
          $ref: '#/components/responses/ShowBlockedTimePreset'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/blocked-time-presets/{blockedTimePresetId}:
    parameters:
      - $ref: '#/components/parameters/blockedTimePresetId'
    get:
      summary: Get a blocked-time preset
      operationId: getBlockedTimePreset
      tags:
        - BlockedTimePresets
      description: |
        Returns a single `BlockedTimePreset` by ID. Useful when editing
        the preset or copying its values into a one-off `BlockedTime`.

        Requires the `RESERVATIONS_VIEW` permission on the preset's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowBlockedTimePreset'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a blocked-time preset
      operationId: updateBlockedTimePreset
      tags:
        - BlockedTimePresets
      description: |
        Updates an existing `BlockedTimePreset`. `name` is required;
        other fields fall back to their existing values when omitted.

        Requires the `SETTINGS_MANAGE` permission on the preset's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateBlockedTimePreset'
      responses:
        '200':
          $ref: '#/components/responses/ShowBlockedTimePreset'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a blocked-time preset
      operationId: deleteBlockedTimePreset
      tags:
        - BlockedTimePresets
      description: |
        Soft-deletes the preset. Already-created `BlockedTime`s are
        unaffected — deleting a preset only removes it from the picker
        UI. Use `POST /shop/blocked-time-presets/{blockedTimePresetId}/restore`
        to bring it back.

        Requires the `SETTINGS_MANAGE` permission on the preset's site.
      responses:
        '204':
          description: The preset was deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/blocked-time-presets/{blockedTimePresetId}/copy:
    parameters:
      - $ref: '#/components/parameters/blockedTimePresetId'
    post:
      summary: Copy a blocked-time preset
      operationId: copyBlockedTimePreset
      tags:
        - BlockedTimePresets
      description: |
        Duplicates an existing `BlockedTimePreset` into a new record with
        overridden `name` (required). Other fields fall back to the
        source preset's values unless overridden.

        Requires the `SETTINGS_MANAGE` permission on the source preset's
        site.
      requestBody:
        $ref: '#/components/requestBodies/CopyBlockedTimePreset'
      responses:
        '201':
          $ref: '#/components/responses/ShowBlockedTimePreset'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/blocked-time-presets/{blockedTimePresetId}/restore:
    parameters:
      - $ref: '#/components/parameters/blockedTimePresetId'
    post:
      summary: Restore a deleted blocked-time preset
      operationId: restoreBlockedTimePreset
      tags:
        - BlockedTimePresets
      description: |
        Restores a soft-deleted `BlockedTimePreset` so it appears in the
        picker again. Idempotent — restoring an already-live preset is
        a no-op.

        Requires the `SETTINGS_MANAGE` permission on the preset's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowBlockedTimePreset'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/blocked-times:
    get:
      summary: List blocked times
      operationId: listBlockedTimes
      tags:
        - BlockedTimes
      description: |
        Returns every `BlockedTime` at the given site whose window
        intersects the `date_from`..`date_to` range. Use this to render
        the operator calendar's "blocked" overlays alongside bookings
        and appointments.

        Both `date_from` and `date_to` are required and inclusive.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateFromRequired'
        - $ref: '#/components/parameters/dateToRequired'
      responses:
        '200':
          $ref: '#/components/responses/ListBlockedTimes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    post:
      summary: Create a blocked time
      operationId: createBlockedTime
      tags:
        - BlockedTimes
      description: |
        Carves a window out of one or more resource calendars
        (practitioners, rooms, or bookable areas). At least one of
        `practitioner_ids`, `room_ids`, or `area_ids` must be non-empty.

        If `recurrence.weekdays` is set, the server fans the block out
        across matching weekdays within
        `recurrence.date_from`..`recurrence.date_to` (max 366 days). The
        first ~30 occurrences are created synchronously; the remainder
        are queued via an async job.

        Requires the `RESERVATIONS_MANAGE` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      requestBody:
        $ref: '#/components/requestBodies/CreateBlockedTime'
      responses:
        '201':
          $ref: '#/components/responses/ShowBlockedTime'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/blocked-times/{blockedTimeId}:
    parameters:
      - $ref: '#/components/parameters/blockedTimeId'
    get:
      summary: Get a blocked time
      operationId: getBlockedTime
      tags:
        - BlockedTimes
      description: |
        Returns a single `BlockedTime` by ID. Useful when reopening the
        calendar tile to edit it, or to verify a record was created with
        the expected resource targets.

        Requires the `RESERVATIONS_VIEW` permission on the blocked
        time's site.
      responses:
        '200':
          $ref: '#/components/responses/ShowBlockedTime'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a blocked time
      operationId: updateBlockedTime
      tags:
        - BlockedTimes
      description: |
        Updates an existing `BlockedTime`. Fields are individually
        optional. Use the `old_*` / `new_*` pairs to swap a single
        resource (practitioner, room, or area) without resubmitting the
        full ID list.

        The response is `201 Created` when the update split a recurring
        blocked time into a new instance (so a new ID is returned) and
        `200 OK` otherwise.

        Requires the `RESERVATIONS_MANAGE` permission on the blocked
        time's site.
      requestBody:
        $ref: '#/components/requestBodies/UpdateBlockedTime'
      responses:
        '200':
          $ref: '#/components/responses/ShowBlockedTime'
        '201':
          $ref: '#/components/responses/ShowBlockedTime'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a blocked time
      operationId: deleteBlockedTime
      tags:
        - BlockedTimes
      description: |
        Removes a single `BlockedTime`. Recurring instances must be
        deleted individually — there is no bulk-delete-the-series
        operation.

        Requires the `RESERVATIONS_MANAGE` permission on the blocked
        time's site.
      responses:
        '204':
          description: The blocked time was deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/course-types:
    parameters:
      - $ref: '#/components/parameters/requiredSiteId'
      - $ref: '#/components/parameters/pageParam'
      - $ref: '#/components/parameters/perPageParam'
      - $ref: '#/components/parameters/archivedQuery'
      - $ref: '#/components/parameters/parameters_offeringId-7'
      - $ref: '#/components/parameters/parameters_categoryId-6'
    get:
      summary: List course types
      description: |
        Returns a paginated list of `CourseType`s configured at the given
        site, ordered by name. Use this to power a settings dashboard or
        to populate a course-credit selector in the shopfront. The list
        includes archived items only when `archived=true` is passed.

        Filter by a specific offering with `offering_id` (matches against
        the course type's `offerings` array) or by category with
        `category_id`.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listCourseTypes
      tags:
        - CourseTypes
      responses:
        '200':
          $ref: '#/components/responses/ListCourseTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    post:
      summary: Create a course type
      description: |
        Creates a new `CourseType` at the site referenced via the
        `Trybe-Site-Id` header (and the `site_id` query parameter). The
        minimum body is `name`; everything else has a sensible default.

        On create the server provisions an internal `Coupon` to track
        redemptions of the course type's credits, unless `coupon_id` is
        supplied. The new `CourseType.coupon_id` is set to the resulting
        coupon's ID.

        Requires the `SETTINGS_MANAGE` permission on the site.
      operationId: createCourseType
      tags:
        - CourseTypes
      requestBody:
        $ref: '#/components/requestBodies/CreateCourseType'
      responses:
        '201':
          $ref: '#/components/responses/ShowCourseTypeEnvelope'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/exports/appointment-types:
    get:
      summary: Queue an export of appointment types
      operationId: queueAppointmentTypesExport
      tags:
        - Reports
      description: |
        Queues an asynchronous CSV export of every active `AppointmentType`
        at the given site, including pricing, durations, resource
        requirements, and visibility flags. Use this to back up your
        catalogue before bulk edits, or to feed appointment data into an
        external analytics tool.

        The response is a `QueuedJob` whose `output.url` will eventually
        contain a signed download URL once the export has completed.
        Poll the job (or subscribe to webhook notifications) until
        `status` is `complete`.

        Requires the `SETTINGS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/exports/area-booking-types:
    get:
      summary: Queue an export of area booking types
      operationId: queueAreaBookingTypesExport
      tags:
        - Reports
      description: |
        Queues an asynchronous CSV export of every active `AreaBookingType`
        at the given site (e.g. cabana hire, treatment-area rentals).
        The file lists prices, durations, capacities, and the bookable
        areas each type is offered against.

        The response is a `QueuedJob`. Poll until `status` is `complete`
        then read `output.url` for the signed download.

        Requires the `SETTINGS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/exports/package-types:
    get:
      summary: Queue an export of packages
      operationId: queuePackageTypesExport
      tags:
        - Reports
      description: |
        Queues an asynchronous CSV export of every active `Package` at
        the given site, including pricing, validity, item choices, and
        each package's enabled offerings. Useful for catalogue audits
        before a pricing run or when migrating to a new site.

        The response is a `QueuedJob`; the export file appears at
        `output.url` once `status` becomes `complete`.

        Requires the `SETTINGS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/exports/retail-products:
    get:
      summary: Queue an export of retail products
      operationId: queueRetailProductsExport
      tags:
        - Reports
      description: |
        Queues an asynchronous CSV export of every retail `Product` at the
        given site, including SKU, barcode, pricing, tax configuration,
        stock-tracking flags, and brand assignments. The resulting file is
        suitable for re-import into an inventory or accounting system.

        The response is a `QueuedJob`; download the export from
        `output.url` once `status` becomes `complete`.

        Requires the `SETTINGS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/exports/session-types:
    get:
      summary: Queue an export of session types
      operationId: queueSessionTypesExport
      tags:
        - Reports
      description: |
        Queues an asynchronous CSV export of every active `SessionType`
        at the given site — scheduled classes, group activities, fitness
        sessions. The file includes capacities, base pricing, durations,
        and which categories the session belongs to.

        The response is a `QueuedJob`. Poll its `status` until it is
        `complete`; the resulting download URL is in `output.url`.

        Requires the `SETTINGS_VIEW` permission on the site.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/item-availability/appointment-slots/{siteId}/{appointmentTypeId}:
    parameters:
      - $ref: '#/components/parameters/siteIdPath'
      - $ref: '#/components/parameters/appointmentTypeIdPath'
    get:
      summary: List appointment slots
      operationId: listAppointmentSlotsByRange
      tags:
        - Availability
      description: |
        Returns every bookable slot for the given `AppointmentType` at
        the given site between `date_time_from` and `date_time_to`.
        Each entry includes the slot's start/end time, eligible
        practitioners, current capacity, and the per-slot price.

        For ranges of one day or less the server runs a live
        availability check; longer ranges fall back to the cached
        schedule.

        `exclude_appointments` / `exclude_basket_items` let you ignore
        existing bookings or basket items during an edit flow so the
        item being edited doesn't block itself.
      parameters:
        - $ref: '#/components/parameters/dateTimeFromRequired'
        - $ref: '#/components/parameters/dateTimeToRequired'
        - $ref: '#/components/parameters/durationOverride'
        - $ref: '#/components/parameters/practitionerIdFilter'
        - $ref: '#/components/parameters/excludeAppointmentsFilter'
        - $ref: '#/components/parameters/excludeBasketItemsFilter'
        - $ref: '#/components/parameters/basketIdFilter'
        - $ref: '#/components/parameters/guestIdFilter'
        - $ref: '#/components/parameters/requiredQuantityFilter'
      responses:
        '200':
          $ref: '#/components/responses/ListAppointmentSlotsByRange'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/item-availability/area-booking-slots/{areaBookingTypeId}:
    parameters:
      - $ref: '#/components/parameters/areaBookingTypeIdPath'
    get:
      summary: List area-booking slots
      operationId: listAreaBookingSlotsByRange
      tags:
        - Availability
      description: |
        Returns every bookable slot for the given `AreaBookingType`
        between `date_time_from` and `date_time_to`. The range may not
        exceed one day — large windows are rejected with `400 Bad
        Request`.

        Slots are ordered earliest first; ties on start time are
        broken by shortest duration first. Pass `quantity` to size the
        slot up for multiple guests (mutually exclusive with `guest_id`).
      parameters:
        - $ref: '#/components/parameters/dateTimeFromRequired'
        - $ref: '#/components/parameters/dateTimeToRequired'
        - $ref: '#/components/parameters/durationOverride'
        - $ref: '#/components/parameters/excludeBookingsFilter'
        - $ref: '#/components/parameters/excludeBasketItemsFilter'
        - $ref: '#/components/parameters/basketIdFilter'
        - $ref: '#/components/parameters/guestIdFilter'
        - $ref: '#/components/parameters/quantityFilter'
      responses:
        '200':
          $ref: '#/components/responses/ListAreaBookingSlotsByRange'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/item-availability/multi-appointment-slots:
    post:
      summary: List combined slots for multiple appointment types
      operationId: actionCheckMultiAppointmentAvailability
      tags:
        - Availability
      description: |
        Returns the set of start times on a given day where every
        requested `AppointmentType` can be booked back-to-back at the
        same site. Used by the booking UI when a customer adds multiple
        appointments to their basket and expects them to chain together.

        The response is a list of `MultiAppointmentSlotGroup`s — one per
        viable start time, each containing the individual slots in
        order.

        > **Deprecated.** The server logs every call to this endpoint
        > as a deprecated request. Prefer building the chain with
        > per-type `appointment-slots` calls if you are starting from
        > scratch.
      requestBody:
        $ref: '#/components/requestBodies/MultiAppointmentAvailability'
      responses:
        '200':
          $ref: '#/components/responses/ListMultiAppointmentSlots'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/item-availability/offering-dates:
    get:
      summary: List availability by day for an offering
      operationId: listOfferingDateAvailability
      tags:
        - Availability
      description: |
        Returns one `OfferingDateAvailability` per day in the
        `date_from`..`date_to` range, indicating whether the offering
        has any bookable slots on that day plus the cheapest slot
        price. Use this to drive a calendar UI that greys-out unbookable
        days without firing a slot-level query per day.

        The maximum supported range is 31 days. Larger ranges return
        `400 Bad Request`.

        Supports `appointment`, `session`, `package`, and `area_booking`
        offering types.
      parameters:
        - $ref: '#/components/parameters/parameters_dateFromRequired'
        - $ref: '#/components/parameters/parameters_dateToRequired'
        - $ref: '#/components/parameters/offeringIdRequired'
        - $ref: '#/components/parameters/offeringTypeRequired'
        - $ref: '#/components/parameters/quantityFilter'
        - $ref: '#/components/parameters/partnerIdFilter'
      responses:
        '200':
          $ref: '#/components/responses/ListOfferingDates'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/item-availability/package-slots/{packageId}/choices/{choiceId}:
    parameters:
      - $ref: '#/components/parameters/packageIdPath'
      - $ref: '#/components/parameters/packageChoiceIdPath'
    get:
      summary: List bookable slots for a package choice
      operationId: listPackageChoiceSlots
      tags:
        - Availability
      description: |
        Returns every bookable slot for one of the items in a
        `Package`'s choice list. Each entry includes the
        `package_item_id` so the caller can attribute the slot back to
        the right choice when adding to a basket.

        The slot shape mirrors the per-offering availability endpoints
        (`appointment-slots`, `area-booking-slots`, etc.) — the
        underlying offering type drives which fields are populated.
      parameters:
        - $ref: '#/components/parameters/dateTimeFromRequired'
        - $ref: '#/components/parameters/dateTimeToRequired'
        - $ref: '#/components/parameters/basketIdFilter'
        - $ref: '#/components/parameters/guestIdFilter'
      responses:
        '200':
          $ref: '#/components/responses/ListPackageChoiceSlots'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/item-availability/products/{productId}:
    parameters:
      - $ref: '#/components/parameters/productIdPath'
    get:
      summary: Get product stock availability
      operationId: getProductAvailability
      tags:
        - Availability
      description: |
        Returns the current sellable stock for the given `Product` at
        its site. Stock-tracking products return their on-hand count;
        non-tracking products return a large sentinel `quantity_available`
        (effectively unlimited).

        Use this just before adding a product to a basket to confirm
        the unit is still purchasable.
      responses:
        '200':
          $ref: '#/components/responses/ShowProductAvailability'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/item-availability/sessions/{siteId}/{sessionTypeId}:
    parameters:
      - $ref: '#/components/parameters/siteIdPath'
      - $ref: '#/components/parameters/sessionTypeIdPath'
    get:
      summary: List session occurrences
      operationId: listSessionOccurrences
      tags:
        - Availability
      description: |
        Returns every scheduled `SessionType` occurrence between
        `date_time_from` and `date_time_to`, with current capacity and
        pricing. Use this to build the customer-facing session
        calendar.

        Unlike appointments, session occurrences are pre-scheduled —
        the endpoint reads the published rota rather than computing
        slots from rules.
      parameters:
        - $ref: '#/components/parameters/dateTimeFromRequired'
        - $ref: '#/components/parameters/dateTimeToRequired'
      responses:
        '200':
          $ref: '#/components/responses/ListSessionOccurrences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/cancel:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Cancel an order (action variant)
      tags:
        - Orders
      operationId: actionCancelOrder
      description: |
        Cancel a submitted order. Functionally equivalent to `DELETE
        /shop/orders/{orderId}` but exposed as a POST action so it can sit
        alongside the other lifecycle transitions (`reserve`, `submit`,
        `settle`, `no-show`) under a consistent `POST .../{verb}` shape.

        Each line item is cancelled in turn — bookings (appointments,
        area bookings, sessions, table reservations) are cancelled and any
        held resources released; purchases (vouchers, memberships, retail
        products) are voided; and any package items follow the cancellation
        rules of their underlying components. Payments remain attached to
        the order so they can be refunded separately via `POST
        /shop/orders/{orderId}/payments/{paymentId}/refunds` or absorbed
        into a credit note.

        Fires the internal `BasketCancelled` event, which downstream
        integrations subscribe to for PMS/CRM sync.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/checkout-link:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Generate a hosted checkout link for an order
      tags:
        - Orders
      operationId: createOrderCheckoutLink
      description: |
        Generate a signed, short-lived URL that drops a customer into the
        site's hosted checkout flow with this order pre-loaded. Used when
        an operator builds an order on the customer's behalf — for example
        a concierge booking by phone — and wants to hand the final payment
        step over to the customer via email or SMS.

        The link is valid for 15 minutes from issue. Each call mints a
        fresh URL; older links continue to work until their own expiry.

        Returns `400 Bad Request` if the order is in a state that no
        longer accepts updates (settled, cancelled, etc.).
      responses:
        '200':
          $ref: '#/components/responses/CreateOrderCheckoutLink'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/discounts-v2:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
  /shop/orders/{orderId}/discounts/{discountId}/recalculate:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/discountId'
    post:
      summary: Recalculate an order-level discount
      tags:
        - Orders
      operationId: actionRecalculateOrderDiscount
      description: |
        Recompute the value of an existing order-level discount against
        the current state of the order. Used after the operator has
        changed the order's contents — added or removed items, applied a
        coupon, attached a voucher — to make sure the discount still
        reflects the correct calculated amount.

        The discount keeps its original `discount_type_code`, `amount_type`
        and `discount_amount`; only the derived fields
        (`calculated_amount`, line-level allocations) are refreshed.
        Returns the updated discount.

        A no-op if nothing has changed — safe to call defensively.
      responses:
        '200':
          $ref: '#/components/responses/RecalculateOrderDiscount'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/items/{itemId}/discounts-v2:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
  /shop/orders/{orderId}/items/{itemId}/package-items:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
    post:
      summary: Add a package item to a package order item
      tags:
        - Orders
      operationId: createOrderItemPackageItem
      description: |
        Add a single child item to a parent package order item. Used after
        creating the package line via `POST /shop/orders/{orderId}/items`
        to fulfil each of the package's `choices` — for example picking
        which treatment to take as the "massage" slot in a spa day
        package, and which group class to attend as the "fitness" slot.

        `choice_id` names the slot being filled and `option_id` names the
        specific offering being chosen. The combination must match the
        parent package's configured choices and options.

        `item_configuration` carries the per-item scheduling — time,
        duration, room, practitioners, areas — and is the preferred place
        to set those fields. The top-level `time`, `duration`,
        `practitioner_ids`, `room_id` and `area_ids` fields remain for
        backward compatibility but are deprecated and will be removed in a
        future major version.

        On success the parent item is reloaded with the new child item
        nested in its `package_items` array.

        Returns `400 Bad Request` if the choice/option pair is invalid,
        the resources aren't available, or the parent package is in a
        state that no longer accepts new package items.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderItemPackageItem'
      responses:
        '201':
          $ref: '#/components/responses/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/itinerary:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Retrieve an itinerary grouped by guest
      tags:
        - Orders
      operationId: getOrderItinerary
      description: |
        Retrieve the order's itinerary — the list of bookings on the
        order, grouped first by which guest they're for and then by
        date. Used by the operator-facing day-of-arrival view to print or
        display a per-guest schedule.

        Each guest bucket lists the guest's name(s) plus one entry per
        date the guest has a booking on. Each date entry lists the
        bookings (`name`, `start_time`, `end_time`) sorted by start time.

        Purchases (vouchers, products, memberships) are not included —
        only items that produce a scheduled booking.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderItinerary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/itinerary/doc:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Generate a downloadable itinerary document
      tags:
        - Orders
      operationId: getOrderItineraryDoc
      description: |
        Generate a Word document version of the order's itinerary and
        return a signed download URL. The document is rendered in the
        site's default locale (not the caller's) so that operators
        printing for guests get the version the guest will read.

        The download URL is short-lived; treat it as single-use and fetch
        a fresh one for each download. The document content matches the
        JSON itinerary returned by `GET /shop/orders/{orderId}/itinerary`.
      responses:
        '200':
          $ref: '#/components/responses/GetOrderItineraryDoc'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/lead-booker:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Update the order's lead booker
      tags:
        - Orders
      operationId: actionUpdateOrderLeadBooker
      description: |
        Update the lead-booker details on an order. Stores the customer
        contact and tax information against the order header and, when a
        lead-booker `Guest` exists on the order, copies the same first
        and last name through to it so the operator-facing guest list and
        the order header stay aligned.

        `phone` is validated against the site's country code and stored
        in E.164 format. Pass `tax_address_id` to copy one of the
        customer's saved addresses into the order's tax address; pass
        `legal_name` / `tax_id` / `tax_id_type` to record a tax identifier
        against the order for downstream invoicing.

        When `tax_id` is provided, `tax_id_type` is recorded alongside it
        (or left `null` if not supplied). When `tax_id` is absent the
        type is ignored.
      requestBody:
        $ref: '#/components/requestBodies/OrderLeadBooker'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/ledger-lines:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List the ledger lines posted against an order
      tags:
        - Orders
      operationId: listOrderLedgerLines
      description: |
        List every ledger line posted against an order, sorted by
        `ledger_date` ascending. Ledger lines are Trybe's financial
        record of an order — one entry per revenue posting, per payment,
        per refund and per redemption — and form the audit trail used by
        the reporting suite to compute revenue, payment and tax totals.

        Each line carries a `revenue_centre` code (and a human-friendly
        `revenue_centre_name`), an amount split into `gross_amount` and
        `net_amount` in the order's currency, plus references to the
        `payable` (the thing being charged — usually an order or a
        payment) and the `causer` (the user or system process that
        triggered the posting).

        The response is not paginated; orders typically have tens of
        ledger lines and rarely hundreds.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderLedgerLines'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/lock:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Lock an order
      tags:
        - Orders
      operationId: actionLockOrder
      description: |
        Lock the order to prevent further edits. Once locked, the order's
        items, payments and other sub-resources reject mutation attempts
        with `403 Forbidden`. Used to freeze an order during a
        settlement, audit or close-of-day process; pair with `POST
        /shop/orders/{orderId}/unlock` to release the lock.

        The action is idempotent — locking an already-locked order
        returns the same response without error. Records a `locked`
        audit-log entry against the order.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/no-show:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Mark an order as no-show
      tags:
        - Orders
      operationId: actionMarkOrderNoShow
      description: |
        Mark the order as a no-show — used when the customer didn't turn
        up for a scheduled booking and the operator wants to track the
        miss for revenue and reporting purposes without going through the
        standard cancellation flow. The order remains valid (payments
        stay attached, items aren't released) but is flagged as
        `no_show` for reporting.

        Fires the internal `BasketNoShowed` event, which downstream
        integrations subscribe to for PMS/CRM sync.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/overpayment-to-voucher:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Transfer order overpayment to a new voucher
      tags:
        - Orders
      operationId: actionTransferOrderOverpaymentToVoucher
      description: |
        Move an order's overpayment balance into a freshly-issued
        voucher. Used when a customer has paid more than the order's
        total — for example after a partial refund or a price
        adjustment — and the operator wants to push the surplus into a
        gift voucher rather than refunding it back to the original
        payment method.

        Specify the `voucher_type_id` to choose which `VoucherType` the
        new voucher should inherit its expiry, terms and presentation
        from. The voucher type must belong to the order's site.

        On success the new `VoucherCode` is returned. The order's
        payment ledger picks up a redemption line so the overpayment no
        longer appears in the outstanding balance.

        Common failure modes:

        - `400 Bad Request` — the order has no overpayment, the voucher
          type doesn't exist on this site, or the underlying voucher
          issuance failed (typically a configuration problem on the
          voucher type).
      requestBody:
        $ref: '#/components/requestBodies/OrderOverpaymentToVoucher'
      responses:
        '201':
          $ref: '#/components/responses/CreateOrderOverpaymentVoucher'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/payments/{paymentId}/charge:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_paymentId-2'
    post:
      summary: Charge a payment
      tags:
        - Orders
      operationId: actionChargeOrderPayment
      description: |
        Trigger a charge against a payment that has been recorded but
        not yet captured. Used for `on_demand` capture-method payments
        that have a stored payment method attached (e.g. saved card on
        file): this endpoint instructs the processor to attempt the
        capture immediately.

        Returns the updated `Payment` with its new status — typically
        `paid` when the capture succeeds, or `failed` with a
        `failure_reason` when it doesn't.

        Returns `400 Bad Request` if the payment can't be charged in its
        current state (e.g. already paid, expired, or no stored payment
        method).
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderPayment'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/payments/{paymentId}/refunds:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_paymentId-2'
    post:
      summary: Refund a payment
      tags:
        - Orders
      operationId: createOrderPaymentRefund
      description: |
        Issue a refund against a payment. The `amount` is taken from the
        payment's `refundable_amount` and routed through the payment's
        processor (Stripe, Adyen, etc.) — the refund only succeeds if
        the processor confirms it. Successful refunds reduce the
        payment's `refundable_amount` and surface in the order's
        `refunds` list and ledger.

        For settled orders, pass `allocations` to declare which items
        the refund should be attributed to and in what amounts. Without
        `allocations` on a settled order the refund is allocated
        proportionally across all line items. On unsettled orders
        `allocations` is ignored — the refund is simply taken off the
        outstanding balance.

        Payments whose processor is `pms_folio` or `external_voucher`
        accept an optional `processor` override of `manual`: this lets
        an operator record the refund inside Trybe without
        round-tripping the external system (used when the refund is
        being recorded retroactively or the external system is
        unavailable).

        `notes` is plain text only — HTML markup is rejected.

        Common failure modes:

        - `400 Bad Request` — the refund amount exceeds the payment's
          refundable balance, the processor rejected the refund, or the
          payment is in a state that doesn't accept refunds.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderPaymentRefund'
      responses:
        '201':
          $ref: '#/components/responses/CreateOrderPaymentRefund'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/postings:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List the PMS postings for an order
      tags:
        - Orders
      operationId: listOrderPostings
      description: |
        List the ledger-line postings that have been forwarded to the
        site's PMS (Property Management System) integration. Each
        posting is a record of a charge or payment that Trybe pushed
        out to the PMS — used by reconciliation workflows to verify
        that Trybe's view of revenue matches the PMS's.

        Results are scoped to the site's currently-configured PMS
        integration. Sorted by `created_at` ascending. Not paginated.

        Returns an empty list for sites without a PMS integration
        configured.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderPostings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/qr-code:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Retrieve a QR code for an order
      tags:
        - Orders
      operationId: getOrderQrCode
      description: |
        Returns a PNG image encoding `TRYBE_ORDER_{orderId}` as a QR
        code. The Trybe-prefixed payload lets the Trybe operator app
        distinguish order codes from other QR payloads it scans, and
        avoids decoding ambiguity with raw IDs.

        The response is cached for one hour (`Cache-Control:
        public, max-age=3600`) — the encoded payload doesn't change for
        the lifetime of the order.

        No authentication is required for this endpoint, matching the
        behaviour of `print-pos-receipt` and the other operator-facing
        print routes; the order ID is the secret.
      responses:
        '200':
          description: A PNG-encoded QR code for the order.
          content:
            image/png:
              schema:
                type: string
                format: binary
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/receipt:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Generate a receipt document for an order
      tags:
        - Orders
      operationId: getOrderReceipt
      description: |
        Generate a fiscal receipt document for the order. The document
        is built from the order's non-deposit, non-redemption ledger
        lines and rendered by the site's configured fiscal-receipt
        generator. The actual document type depends on the site's
        integration — most sites return a JSON resource describing the
        receipt's contents, but a few PMS integrations return an HTML
        document directly.

        Pass an `Accept: text/html` request header to receive an HTML
        body in the response when the generator produces one. Without
        the header, callers always receive the structured JSON form.

        Returns `404 Not Found` when the site doesn't have a fiscal
        receipt integration configured.
      responses:
        '200':
          description: |
            The generated receipt document. Either JSON (default) or
            HTML when the site's integration produces it and the
            request opted in via `Accept: text/html`.
          content:
            application/json:
              schema:
                title: ShowOrderReceipt
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/OrderReceiptDocument'
                required:
                  - data
            text/html:
              schema:
                type: string
                description: |
                  HTML body of the receipt. Returned only when the
                  site's receipt generator produces HTML and the
                  caller opts in via `Accept: text/html`.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/rmt-receipt:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Generate an RMT receipt document for an order
      tags:
        - Orders
      operationId: getOrderRmtReceipt
      description: |
        Generate a Registered Massage Therapist (RMT) receipt document for a
        submitted or settled order. Only available for Canadian sites.

        Pass an `Accept: text/html` request header to receive an HTML body in the
        response when the generator produces one. Without the header, callers
        always receive the structured JSON form.

        Returns `403 Forbidden` when the site is not a Canadian site.
        Returns `422 Unprocessable Entity` when the order has not been checked out.
      responses:
        '200':
          description: |
            The generated Registered Massage Therapist (RMT) receipt document.
            Either JSON (default) or HTML when the site's generator produces it
            and the request opted in via `Accept: text/html`.
          content:
            application/json:
              schema:
                title: ShowOrderRmtReceipt
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/RmtReceiptDocument'
                required:
                  - data
            text/html:
              schema:
                type: string
                description: |
                  HTML body of the RMT receipt. Returned only when the generator
                  produces HTML and the caller opts in via `Accept: text/html`.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/rmt-receipt/email:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Email an RMT receipt for an order
      tags:
        - Orders
      operationId: actionEmailOrderRmtReceipt
      description: |
        Send the Registered Massage Therapist (RMT) receipt for a submitted or
        settled order to the order's email address. Only available for Canadian sites.

        Returns `403 Forbidden` when the site is not a Canadian site.
        Returns `400 Bad Request` when the order does not have an email address.
        Returns `422 Unprocessable Entity` when the order has not been checked out.
      responses:
        '200':
          description: The RMT receipt was sent successfully.
          content:
            application/json:
              schema:
                title: EmailOrderRmtReceiptResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    title: EmailOrderRmtReceiptData
                    type: object
                    additionalProperties: false
                    properties:
                      sent:
                        type: boolean
                        example: true
                    required:
                      - sent
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/tax-receipt:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: Generate a tax receipt document for an order
      tags:
        - Orders
      operationId: getOrderTaxReceipt
      description: |
        Generate a tax receipt document for a settled order.

        Pass an `Accept: text/html` request header to receive an HTML body in the
        response when the generator produces one. Without the header, callers
        always receive the structured JSON form.

        Returns `422 Unprocessable Entity` when the order has not been checked out.
      responses:
        '200':
          description: |
            The generated tax receipt document. Either JSON (default) or HTML when
            the site's generator produces it and the request opted in via
            `Accept: text/html`.
          content:
            application/json:
              schema:
                title: ShowOrderTaxReceipt
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/TaxReceiptDocument'
                required:
                  - data
            text/html:
              schema:
                type: string
                description: |
                  HTML body of the tax receipt. Returned only when the generator
                  produces HTML and the caller opts in via `Accept: text/html`.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/tax-receipt/email:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Email a tax receipt for an order
      tags:
        - Orders
      operationId: actionEmailOrderTaxReceipt
      description: |
        Send the tax receipt for a settled order to the order's email address.

        Returns `400 Bad Request` when the order does not have an email address.
        Returns `422 Unprocessable Entity` when the order has not been checked out.
      responses:
        '200':
          description: The tax receipt was sent successfully.
          content:
            application/json:
              schema:
                title: EmailOrderTaxReceiptResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    title: EmailOrderTaxReceiptData
                    type: object
                    additionalProperties: false
                    properties:
                      sent:
                        type: boolean
                        example: true
                    required:
                      - sent
                required:
                  - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/refundable-items:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_paymentId-3'
    get:
      summary: List the refundable items on an order
      tags:
        - Orders
      operationId: listOrderRefundableItems
      description: |
        List the items that can currently be refunded against the order,
        alongside any service-charge and tip components when they carry
        a positive balance. Used by the refund flow to render the
        operator-facing "what can I refund?" picker.

        Pass `payment_id` to scope the list to what can be refunded against
        a specific payment (tips linked to that payment; items attributed
        via payment item revenues when available). On single-payment orders
        the parameter is optional and behaviour matches the unscoped list.

        Each entry surfaces the line item's identifier, type, refundable
        amount and an `allocation_hint` the refund processor uses when
        splitting a refund across multiple items. The endpoint never
        issues a refund itself — `POST
        /shop/orders/{orderId}/payments/{paymentId}/refunds` is the
        write side.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderRefundableItems'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/refunds:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_revenueCentre-5'
    get:
      summary: List the refunds against an order
      tags:
        - Orders
      operationId: listOrderRefunds
      description: |
        List every refund that has been recorded against the order,
        across every payment. Refunds carry the amount, status, the
        payment they were issued against, operator notes, and how the
        refund was allocated across basket items / revenue centres.

        Optionally filter with `revenue_centre` to return only refunds
        that allocate to that centre. The response is not paginated;
        most orders have a handful of refunds at most.

        To create a new refund, use `POST
        /shop/orders/{orderId}/payments/{paymentId}/refunds`.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderRefunds'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/refunds/{refundId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/refundId'
    get:
      summary: Retrieve a single refund
      tags:
        - Orders
      operationId: getOrderRefund
      description: |
        Retrieve a single refund recorded against the order. The
        response carries the refund's amount, status, the payment it was
        issued against and the processor-specific data (chargeback IDs,
        PMS sync state, etc.) used downstream by reconciliation jobs.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderRefund'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/reserve:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Reserve an order's resources
      tags:
        - Orders
      operationId: actionReserveOrder
      description: |
        Place a short-lived hold on the underlying resources for every
        booking item in the order — practitioners, rooms, equipment,
        areas — so that another caller can't grab the same slot while
        the order is being finalised. Reservations are cooperative: they
        block other bookings only when the system explicitly checks (via
        the availability service), and they expire automatically after
        `reserve_mins` minutes.

        Pass `reserve_mins` to override the site's default hold time;
        omit it to use the default. The value must be greater than zero.

        Returns `400 Bad Request` when one or more items can no longer be
        held (the underlying availability has slipped since the order
        was built).
      requestBody:
        $ref: '#/components/requestBodies/ReserveOrder'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/orders/{orderId}/revenues:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    get:
      summary: List the revenue breakdown for an order
      tags:
        - Orders
      operationId: listOrderRevenues
      description: |
        Return the order's revenue rolled up by revenue centre. Each
        entry carries the revenue centre code, the gross and net
        amounts (in the lowest denomination of the order's currency)
        and the tax components that contributed to the gross figure.
        Used by the operator-facing revenue panel and by the reporting
        suite to drill down into a single order's contribution to a
        daily or monthly total.

        The response's `meta.currency` mirrors the order's currency so
        that callers don't have to look it up on the parent order.

        Not paginated.
      responses:
        '200':
          $ref: '#/components/responses/ListOrderRevenues'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/settle:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Settle an order
      tags:
        - Orders
      operationId: actionSettleOrder
      description: |
        Settle the order — the final lifecycle transition that locks the
        order's revenue into the ledger and closes it for further edits.
        Used by automated close-of-day jobs as well as manually by
        operators when an order has been fully paid for and serviced.

        The action is idempotent — settling an already-settled order is a
        no-op and returns the same order.

        Returns `400 Bad Request` when the order can't be settled — for
        example because it has outstanding balance or contains items
        that haven't been fulfilled. The error message describes the
        specific reason.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/submit:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Submit an order
      tags:
        - Orders
      operationId: actionSubmitOrder
      description: |
        Convert a basket into a confirmed order. The endpoint runs the
        final validation pass — checking item availability, payment
        coverage, intake form completion and any site-specific rules — and
        then commits the basket: bookings are confirmed, payments are
        moved out of `pending` where required, and the order's status
        advances out of the basket states.

        The `{orderId}` placeholder is interchangeably called `basket` in
        legacy clients; the route accepts either an order or a basket ID
        pointing at the same record.

        Pass `skip_availability_checks=true` to bypass the second-pass
        availability recheck normally run at submission time. The flag is
        honoured only for users that hold the
        `RESERVATIONS_OVERRIDE_RULES` permission; operators without it
        have the flag silently ignored.

        Failure modes:

        - `400 Bad Request` — the basket isn't valid for submission (e.g.
          insufficient payment, expired availability, integration rule
          violation). The error message describes the specific reason.
        - `400 Bad Request` with the message *"One or more items are now
          unavailable"* — availability changed between basket build and
          submission.
        - `400 Bad Request` with the message *"The basket was unable to be
          submitted. Please try again."* — a transient lock-timeout
          occurred and the caller should retry.

        On success the freshly submitted order is returned with an
        `intake_form_url` field hydrated when one or more items require a
        pre-arrival intake form to be completed.
      requestBody:
        $ref: '#/components/requestBodies/SubmitOrder'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/unlock:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Unlock an order
      tags:
        - Orders
      operationId: actionUnlockOrder
      description: |
        Release a lock previously placed on the order via `POST
        /shop/orders/{orderId}/lock`. Once unlocked the order accepts
        edits again. Requires the `RESERVATIONS_UNLOCK` permission, which
        is typically held by a smaller set of operators than the day-to-
        day lock action.

        The action is idempotent — unlocking an already-unlocked order
        returns the same response without error. Records an `unlocked`
        audit-log entry against the order.
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/vouchers:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
    post:
      summary: Add a voucher payment to an order
      tags:
        - Orders
      operationId: createOrderVoucher
      description: |
        Redeem a voucher code against the order. The voucher's remaining
        balance is applied as a payment against the order — either
        settling the outstanding balance in full or contributing toward
        it depending on the voucher's value. The order is returned with
        the new payment listed in its `payments` array.

        The voucher code must reference a valid, unredeemed
        `VoucherCode` on the order's site. Common failure modes:

        - `400 Bad Request` — the voucher is expired, fully redeemed,
          belongs to a different site, or is in a state that doesn't
          accept new redemptions. The error message describes the
          specific reason.

        Remove a previously-redeemed voucher with `DELETE
        /shop/orders/{orderId}/vouchers/{voucherCode}`.
      requestBody:
        $ref: '#/components/requestBodies/CreateOrderVoucher'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/partner-config/{partnerConfigId}:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
  /shop/partner-config/{partnerConfigId}/availability-rules:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
  /shop/partner-config/{partnerConfigId}/availability-rules/{availabilityRuleId}:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
      - $ref: '#/components/parameters/parameters_availabilityRuleId'
  /shop/partner-config/{partnerConfigId}/availability-rules/{availabilityRuleId}/copy:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
      - $ref: '#/components/parameters/parameters_availabilityRuleId'
  /shop/partner-config/{partnerConfigId}/availability-rules/{availabilityRuleId}/restore:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
      - $ref: '#/components/parameters/parameters_availabilityRuleId'
  /shop/partner-config/{partnerConfigId}/copy:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
  /shop/partner-config/{partnerConfigId}/restore:
    parameters:
      - $ref: '#/components/parameters/partnerConfigId'
  /shop/practitioners/{practitionerId}/rota-for-date:
    parameters:
      - $ref: '#/components/parameters/parameters_practitionerId-4'
    get:
      summary: Get the resolved rota for a single date
      description: |
        Returns the working schedule for a single date for the given
        practitioner. The response blends the recurring rota with any
        custom availability rules that cover the date so the caller can
        render a day-view UI without doing the reconciliation locally.

        `for_date.rules_for_date` is the recommended field to render —
        it points at whichever rule-set (`custom_rules` or
        `rota_availability_rules`) is authoritative for the day.

        Requires the `ROTAS_VIEW` permission on the practitioner's first
        site.
      operationId: getPractitionerRotaForDate
      tags:
        - Practitioners
      parameters:
        - $ref: '#/components/parameters/parameters_date-16'
      responses:
        '200':
          description: The resolved schedule for the date.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PractitionerRotaForDate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    post:
      summary: Override the rota for a single date
      description: |
        Sets the working schedule for a single date for the given
        practitioner via custom availability rules. The endpoint is
        idempotent for the requested date: existing custom rules covering
        the date are cleared (or trimmed if they extend beyond the date)
        before the new rules are applied.

        Submitting an empty `availability_rules` array — or omitting the
        key — blocks the practitioner for the entire day. Submitting
        rules that match the regular rota leaves the rota in charge with
        no custom rules created.

        Returns the same shape as the GET endpoint so callers can re-render
        without a follow-up fetch.

        Requires the `ROTAS_MANAGE` permission on the practitioner's first
        site.
      operationId: updatePractitionerRotaForDate
      tags:
        - Practitioners
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionerRotaForDate'
      responses:
        '200':
          description: The schedule was updated. The response is the same shape as `GET /shop/practitioners/{practitionerId}/rota-for-date`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PractitionerRotaForDate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/practitioners/order:
    get:
      summary: List practitioners in display order
      description: |
        Returns a lightweight, non-paginated list of `PractitionerSummary`
        objects for the given site, sorted by each practitioner's `order`
        field then by `name`. Use this to render an ordering UI without
        pulling the full `Practitioner` payload for every entry.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listPractitionersOrder
      tags:
        - Practitioners
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          description: The practitioners for the site, sorted by `order`.
          content:
            application/json:
              schema:
                title: ListPractitionersOrder
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: Practitioner summaries in display order.
                    items:
                      $ref: '#/components/schemas/PractitionerSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    put:
      summary: Reorder practitioners for a site
      description: |
        Reorders the practitioners at a site in one request. The order of
        `practitioner_ids` in the body determines each practitioner's
        `order` field (first ID → `order: 0`, second → `order: 1`, etc.).
        IDs not listed are unaffected and keep their existing `order`.

        Returns the full ordered list (same shape as the GET response) so
        callers can re-render without a follow-up fetch.

        Requires the `SETTINGS_MANAGE` permission on the site.
      operationId: updatePractitionersOrder
      tags:
        - Practitioners
      requestBody:
        $ref: '#/components/requestBodies/UpdatePractitionersOrder'
      responses:
        '200':
          description: The reordered list of practitioners.
          content:
            application/json:
              schema:
                title: UpdatePractitionersOrderResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: Practitioner summaries in the newly-applied display order.
                    items:
                      $ref: '#/components/schemas/PractitionerSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/shop/appointment-tags:
    get:
      summary: List storefront appointment tags
      operationId: listShopAppointmentTags
      tags:
        - Shop
      description: |
        Returns every `AppointmentTag` configured at the organisation
        level. Tags label appointment types for the storefront UI (e.g.
        "couples", "mens") so customers can filter by interest.

        Tags are organisation-level, not site-level — pass the
        `organisation_id` whose sites you're rendering for.
      parameters:
        - $ref: '#/components/parameters/organisationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/ListShopAppointmentTags'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/shop/appointments:
    get:
      summary: List storefront appointment types
      operationId: listShopAppointmentTypes
      tags:
        - Shop
      description: |
        Returns the customer-facing `AppointmentType`s at the given site
        — only those with `visibility=public` or `visibility=link_only`.
        Use this to render the appointment menu on the booking
        storefront.

        For staff-facing listings (including hidden appointment types)
        use `GET /shop/appointment-types` instead.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/ListShopAppointmentTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/shop/categories:
    get:
      summary: List storefront categories
      operationId: listShopCategories
      tags:
        - Shop
      description: |
        Returns every `Category` configured for the organisation.
        Categories bucket offerings on the storefront ("Spa", "Salon",
        "Fitness") and drive the top-level navigation of the booking
        site.

        Categories are organisation-level, not site-level — pass the
        `organisation_id` whose sites you're rendering for.
      parameters:
        - $ref: '#/components/parameters/organisationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/ListShopCategories'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/shop/offerings:
    get:
      summary: List storefront offerings
      operationId: listShopOfferings
      tags:
        - Shop
      description: |
        Returns every customer-facing `Offering` at the given site —
        appointments, area bookings, packages, products, and sessions —
        in the order they should appear in the storefront listing. The
        shape of each item depends on `offering_type`.

        Optional filters narrow the listing by `category_id`,
        `partner_id`, or `date` (only offerings with availability on the
        given day are returned). When `customer` / `frontend`-guard
        auth is present, the result accounts for the customer's coupon
        codes when calculating displayed pricing.

        This is the public storefront endpoint; results are filtered to
        `visibility=public` and `visibility=link_only` records.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/dateOptional'
        - $ref: '#/components/parameters/categoryIdFilter'
        - $ref: '#/components/parameters/parameters_partnerIdFilter'
      responses:
        '200':
          $ref: '#/components/responses/ListShopOfferings'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/shop/offerings/{offeringType}/{offeringId}/cross-sell:
    parameters:
      - $ref: '#/components/parameters/offeringType'
      - $ref: '#/components/parameters/offeringId'
    get:
      summary: List cross-sell offerings for an offering
      operationId: listShopOfferingCrossSells
      tags:
        - Shop
      description: |
        Returns the configured cross-sell offerings for the given
        `Offering`. Cross-sells are surface elsewhere in the booking
        flow (e.g. "Customers also booked...") to drive add-on
        revenue. The response shape is identical to
        `GET /shop/shop/offerings`.

        Only `appointment`, `package`, and `session` offering types
        expose cross-sells; other types return `404`.
      responses:
        '200':
          $ref: '#/components/responses/ListShopOfferings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/shop/offerings/{offeringType}/{offeringId}/up-sell:
    parameters:
      - $ref: '#/components/parameters/offeringType'
      - $ref: '#/components/parameters/offeringId'
    get:
      summary: List up-sell offerings for an offering
      operationId: listShopOfferingUpSells
      tags:
        - Shop
      description: |
        Returns the configured up-sell offerings for the given
        `Offering`. Up-sells are surfaced at checkout ("Upgrade to...")
        to encourage customers to choose a higher-margin alternative.
        The response shape is identical to
        `GET /shop/shop/offerings`.

        Only `appointment`, `package`, and `session` offering types
        expose up-sells; other types return `404`.
      responses:
        '200':
          $ref: '#/components/responses/ListShopOfferings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/shop/practitioners:
    get:
      summary: List storefront practitioners
      operationId: listShopPractitioners
      tags:
        - Shop
      description: |
        Returns every `Practitioner` working at the given site, with
        only the public-facing fields (name, profile photo, bio, title,
        pronouns). Used to populate practitioner pickers and "Meet the
        team" pages on the booking storefront.

        The result is unpaginated and not site-permission gated — it
        mirrors what a public visitor sees in the storefront UI.
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          $ref: '#/components/responses/ListShopPractitioners'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    post:
      summary: Create a storefront practitioner
      operationId: createShopPractitioner
      tags:
        - Shop
      description: |
        Creates a new `Practitioner` from the storefront-facing API. The
        body uses the same `Practitioner` shape as the admin endpoint;
        this route exists for legacy storefront integrations that already
        target `/shop/shop/practitioners` instead of the canonical
        `/shop/practitioners`.

        Requires the `SETTINGS_MANAGE` permission on each site listed in
        `site_ids`.
      requestBody:
        description: The practitioner to create.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Practitioner'
      responses:
        '201':
          description: The practitioner was created.
          content:
            application/json:
              schema:
                title: CreateShopPractitionerResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Practitioner'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites/{siteId}/integrations/mews/accounting-categories:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/import-room-types:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/outlets:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/payment-types/{paymentTypeId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/paymentTypeId'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/mews/revenue-centres/{revenueCentre}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_revenueCentre-6'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/mews/services:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/mews/settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/mews/tax-rates:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/opera-fias:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/opera-fias/disable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/opera-fias/enable:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/opera-fias/export-split-table:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/sites/{siteId}/integrations/opera-fias/payment-types/{paymentTypeId}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_paymentTypeId'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/opera-fias/revenue-centres/{revenueCentre}:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
      - $ref: '#/components/parameters/parameters_revenueCentre-7'
      - $ref: '#/components/parameters/parameters_integrationConfigId'
  /shop/sites/{siteId}/integrations/opera-fias/settings:
    parameters:
      - $ref: '#/components/parameters/siteId'
        required: true
  /shop/voucher-types/order:
    get:
      summary: List voucher types in display order
      description: |
        Returns a lightweight, non-paginated list of `VoucherTypeSummary`
        objects for the given site, sorted by each voucher type's `order`
        field. Use this to render a drag-and-drop ordering UI without
        pulling the full `VoucherType` payload for every entry.

        Requires the `RESERVATIONS_VIEW` permission on the site.
      operationId: listVoucherTypesOrder
      tags:
        - VoucherTypes
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
      responses:
        '200':
          description: The voucher types for the site, sorted by `order`.
          content:
            application/json:
              schema:
                title: ListVoucherTypesOrder
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: Voucher type summaries in display order.
                    items:
                      $ref: '#/components/schemas/VoucherTypeSummary'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
    put:
      summary: Reorder voucher types for a site
      description: |
        Reorders the voucher types at a site in one request. The order of
        `voucher_type_ids` in the body determines each voucher type's
        `order` field (first ID → `order: 0`, second → `order: 1`, etc.).
        IDs not listed are unaffected and keep their existing `order`.

        Returns no body on success — call `GET /shop/voucher-types/order`
        afterwards to fetch the reordered list.

        Requires the `SETTINGS_MANAGE` permission on the site.
      operationId: updateVoucherTypesOrder
      tags:
        - VoucherTypes
      requestBody:
        $ref: '#/components/requestBodies/UpdateVoucherTypesOrder'
      responses:
        '204':
          description: The voucher types were reordered. No content is returned.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/coupon-codes:
    get:
      summary: List coupon codes across organisations
      description: |
        Returns a paginated list of every `CouponCode` visible to the
        calling user across every organisation they belong to. Use the
        `code` query filter to look up a single redemption code without
        knowing which coupon it belongs to — handy when a customer presents
        a code at point of sale and the staff member needs to navigate to
        the owning coupon.

        Each entry includes the `organisation_id` of the owning coupon so
        consumers can route follow-up calls to the correct
        `/shop/organisations/{organisationId}/...` resource.

        Requires the `RESERVATIONS_VIEW` permission on at least one site.
      operationId: listCrossOrganisationCouponCodes
      tags:
        - CouponCodes
      parameters:
        - $ref: '#/components/parameters/parameters_code-5'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCrossOrganisationCouponCodes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /shop/coupon-codes/{code}/offering-discounts:
    parameters:
      - $ref: '#/components/parameters/parameters_code-3'
    get:
      summary: Get the offering discount for a coupon code
      description: |
        Returns the primary `OfferingDiscount` configured on the coupon
        behind the given redemption `code`. Useful at point of sale when
        you want to preview the offerings a coupon code applies to before
        asking the customer to commit it to a basket.

        The lookup is scoped to the organisation derived from the caller's
        site context: if the code exists in another organisation the
        endpoint returns `404`.

        Requires the `CUSTOMERS_VIEW` permission.
      operationId: getCouponCodeOfferingDiscounts
      tags:
        - CouponCodes
      responses:
        '200':
          $ref: '#/components/responses/ShowCouponCodeOfferingDiscount'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/equipment/{equipmentId}/copy:
    parameters:
      - $ref: '#/components/parameters/equipmentId'
    post:
      summary: Duplicate an equipment item
      description: |
        Creates a copy of an existing `Equipment` item with the supplied
        fields applied on top of the source. Useful when seeding a new
        piece of kit off an existing one — for example cloning a treatment
        table to a second site without rebuilding it from scratch.

        Fields omitted from the body are inherited from the source verbatim.
        Pass `site_id` to clone the equipment into a different site; omit it
        to keep the copy on the source site.

        Requires the `SETTINGS_MANAGE` permission on the target site.
      operationId: copyEquipment
      tags:
        - Equipment
      requestBody:
        $ref: '#/components/requestBodies/CopyEquipment'
      responses:
        '200':
          $ref: '#/components/responses/ShowEquipment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/esc-pos/release/{version}:
    parameters:
      - $ref: '#/components/parameters/releaseAssetId'
  /shop/fias-relay/release/{version}:
    parameters:
      - $ref: '#/components/parameters/parameters_releaseAssetId'
  /shop/intake-form-sections/{intakeFormSectionId}/questions/{intakeFormQuestionId}:
    parameters:
      - $ref: '#/components/parameters/intakeFormSectionId'
      - $ref: '#/components/parameters/intakeFormQuestionId'
    get:
      summary: Get an IntakeFormQuestion
      description: |
        Returns a single `IntakeFormQuestion` by ID, including its
        multiple-choice answers, range constraints, and terms statement
        where applicable.

        Requires the `SETTINGS_VIEW` permission on the section's site.
      operationId: getIntakeFormQuestion
      tags:
        - IntakeForms
      responses:
        '200':
          description: The question was retrieved successfully.
          content:
            application/json:
              schema:
                title: GetIntakeFormQuestion
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/IntakeFormQuestion'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an IntakeFormQuestion
      description: |
        Updates an existing `IntakeFormQuestion` in place. `type` is
        required and triggers the same conditional validation as on
        create (e.g. `multiple_choice_answers` must contain ≥ 2 items
        when `type=multiple_choice`).

        `terms_statement` HTML is re-sanitised against the site's
        allowed-tag list before persisting.

        Requires the `SETTINGS_MANAGE` permission on the section's site.
      operationId: updateIntakeFormQuestion
      tags:
        - IntakeForms
      requestBody:
        $ref: '#/components/requestBodies/UpdateIntakeFormQuestion'
      responses:
        '200':
          description: The question was updated successfully.
          content:
            application/json:
              schema:
                title: UpdateIntakeFormQuestionResponse
                type: object
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/IntakeFormQuestion'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an IntakeFormQuestion
      description: |
        Deletes the question and removes it from the parent section's
        rendered intake form. Submitted answers from existing visits are
        preserved on the underlying `VisitIntakeForm` records (the
        question is no longer fillable, but historical answers remain
        addressable by question ID).

        Requires the `SETTINGS_MANAGE` permission on the section's site.
      operationId: deleteIntakeFormQuestion
      tags:
        - IntakeForms
      responses:
        '204':
          description: The question was deleted successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/integrations/toast/{toastId}/config:
    parameters:
      - $ref: '#/components/parameters/toastId'
  /shop/integrations/toast/{toastId}/reservations:
    parameters:
      - $ref: '#/components/parameters/toastId'
  /shop/integrations/toast/{toastId}/tender:
    parameters:
      - $ref: '#/components/parameters/toastId'
  /shop/offering-availability:
    get:
      summary: Get monthly availability for an offering
      description: |
        Returns one entry per calendar day in the month containing `date`,
        indicating whether the supplied offering is bookable and whether
        any availability rule covers the day at all. Intended for
        powering calendar-month pickers in booking UIs without iterating
        every individual slot.

        The check honours every `available` rule on the offering, then
        subtracts `unavailable` rules; if any window survives for a given
        day the day's `is_available` is `true`.

        Requires the `RESERVATIONS_VIEW` permission on the offering's
        site.
      operationId: listOfferingAvailability
      tags:
        - OfferingAvailability
      parameters:
        - $ref: '#/components/parameters/parameters_date-17'
        - $ref: '#/components/parameters/parameters_offeringType-8'
        - $ref: '#/components/parameters/parameters_offeringId-8'
      responses:
        '200':
          $ref: '#/components/responses/ListOfferingAvailabilityDays'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/offering-availability/add-day-unavailability:
    post:
      summary: Mark a day as unavailable for an offering
      description: |
        Creates (or no-ops on, if one already exists) a one-day
        "unavailable" availability rule on the offering. Equivalent to
        going into the offering's availability calendar and toggling the
        targeted day off.

        Idempotent: if the same `(date, offering)` already has an
        unavailable rule, the existing rule is returned without modification.

        Requires the `SETTINGS_MANAGE` permission on the offering's site.
      operationId: actionAddOfferingDayUnavailability
      tags:
        - OfferingAvailability
      requestBody:
        $ref: '#/components/requestBodies/OfferingDayUnavailability'
      responses:
        '204':
          description: The day was successfully marked unavailable.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/offering-availability/remove-day-unavailability:
    post:
      summary: Clear unavailability for a day on an offering
      description: |
        Removes every `unavailable` availability rule that covers the
        targeted day on the offering. If a rule spans more than the
        targeted day (e.g. a multi-day block), it is split into
        surrounding rules that preserve the unavailability on the days
        that weren't targeted.

        The operation is serialised via a per-offering lock to prevent
        concurrent edits clobbering each other; if another request is
        currently modifying the same offering, the call returns `429 Too
        Many Requests`.

        Requires the `SETTINGS_MANAGE` permission on the offering's site.
      operationId: actionRemoveOfferingDayUnavailability
      tags:
        - OfferingAvailability
      requestBody:
        $ref: '#/components/requestBodies/OfferingDayUnavailability'
      responses:
        '204':
          description: The day's unavailability rules were successfully cleared.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          description: |
            Another request is currently modifying availability rules for
            this offering. Retry after a short backoff.
          content:
            application/json:
              schema:
                title: OfferingAvailabilityLocked
                type: object
                additionalProperties: false
                properties:
                  message:
                    type: string
                    description: A description of the lock-conflict.
  /shop/offering-search/most-popular:
    get:
      summary: List the most popular offerings
      description: |
        Returns the offerings most often sold over the trailing four
        weeks, capped by `per_page` and ordered by sales count descending.
        Useful for "Popular at this site" sections on the storefront and
        operator quick-pick lists.

        Filters mirror the main offering search:

        - `offering_type` accepts a comma-separated list; prefix a type
          with `-` to exclude it (e.g. `appointment,-package`).
        - `practitioner_id` narrows appointment results to those tied to
          the given practitioners.

        Requires the `RESERVATIONS_VIEW` permission on the targeted site.
      operationId: listMostPopularOfferings
      tags:
        - Offerings
      parameters:
        - $ref: '#/components/parameters/parameters_offeringType'
        - $ref: '#/components/parameters/parameters_practitionerId-2'
        - $ref: '#/components/parameters/parameters_siteId-9'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          description: The most popular offerings.
          content:
            application/json:
              schema:
                title: ListMostPopularOfferings
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    description: Offerings ordered by recent sales count.
                    items:
                      $ref: '#/components/schemas/Offering'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/order-by-ref/{orderRef}:
    parameters:
      - $ref: '#/components/parameters/orderRef'
    get:
      summary: Get an order by reference
      description: |
        Looks up an `Order` by the short customer-facing reference Trybe
        issues (e.g. `TRY1234`). Equivalent to
        `GET /shop/orders/{orderId}` but keyed by the human-readable
        reference printed on receipts and emails — useful when an operator
        has the reference but not the order ID.

        The lookup is scoped to the sites the calling user belongs to.
        Pass `site_id` to narrow further. Returns `404` if the reference
        doesn't match any in-scope order.

        Requires the `RESERVATIONS_VIEW` permission on the matching
        order's site.
      operationId: getOrderByRef
      tags:
        - Orders
      parameters:
        - $ref: '#/components/parameters/parameters_siteIdFilter-2'
        - $ref: '#/components/parameters/parameters_genericItemsArray'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrder'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/order-intake-forms/{orderIntakeFormId}:
    parameters:
      - $ref: '#/components/parameters/orderIntakeFormId'
    get:
      summary: List intake forms for an order
      description: |
        Returns one row per (guest, intake form) on the order — completed
        forms, pending ones the guest still needs to fill, and previously
        completed mandatory waivers that roll forward from an earlier
        order. Use this to render an intake-form checklist on the operator
        console or to link a guest to their form via `intake_form_url`.

        Mandatory-waiver behaviour: when a guest on the order has already
        signed a mandatory waiver against this site on a previous order
        (and no new waiver has been issued for the current order), that
        previous waiver is included with `mandatory_waiver=true` and
        `requires_intake_form=false`, so the operator UI shows it as
        satisfied without prompting for a fresh signature.

        Requires the `RESERVATIONS_VIEW` permission on the order's site.
      operationId: listOrderIntakeForms
      tags:
        - Orders
      responses:
        '200':
          $ref: '#/components/responses/ListOrderIntakeForms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/guests/{guestId}/complete-check-in:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_guestId'
    put:
      summary: Complete a guest's check-in for an order
      description: |
        Marks the guest identified by `guestId` as checked in against the
        parent `Order` and checks the guest in to every session booking on
        the order in one call. Idempotent: re-running on an already-checked-in
        guest is a no-op.

        Side effects performed atomically:

        - The order guest's `checked_in_at` timestamp is set to the server's
          current time (if not already set).
        - Every session booking the guest holds on the order is moved to the
          `arrived` stage.
        - A `kiosk_check_in` event is dispatched to the Check-Ins API so
          downstream integrations (e.g. PMS, fiscalisation) are notified.

        Requires the `RESERVATIONS_MANAGE` permission on the order's site.
        No request body.
      operationId: actionCompleteOrderGuestCheckIn
      tags:
        - Orders
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderGuest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/guests/{guestId}/check-out:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_guestId'
    post:
      summary: Check a guest out from an order
      description: |
        Marks the guest identified by `guestId` as checked out against the
        parent `Order` and checks the guest out from every session booking on
        the order in one call. Idempotent: re-running on an already-checked-out
        guest is a no-op.

        Side effects performed atomically:

        - The order guest's `checked_out_at` timestamp is set to the server's
          current time (if not already set).

        Requires the `RESERVATIONS_MANAGE` permission on the order's site.
        No request body.
      operationId: actionCheckOutOrderGuest
      tags:
        - Orders
      responses:
        '200':
          $ref: '#/components/responses/ShowOrderGuest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/labels/{labelId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_labelId'
    post:
      summary: Duplicate a Label
      description: |
        Creates a copy of an existing organisation `Label` with new fields
        applied from the request body. Useful for spinning up a second
        label for another set of sites without rebuilding it from scratch.

        `name` and `site_ids` are required so the copy is distinct from the
        source. `color` is optional and defaults to the source's colour
        when omitted.

        Requires the `SETTINGS_MANAGE` permission on the organisation.
      operationId: copyOrganisationLabel
      tags:
        - Organisations
      requestBody:
        $ref: '#/components/requestBodies/CopyOrganisationLabel'
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/labels/{labelId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_labelId'
    post:
      summary: Restore a Label
      description: |
        Restores a previously soft-deleted organisation `Label`. The label
        reappears in pickers and filters and any records that were tagged
        with it before deletion immediately regain the tag in the UI.

        Requires the `SETTINGS_MANAGE` permission on the organisation. No
        request body.
      operationId: restoreOrganisationLabel
      tags:
        - Organisations
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/sales-channels-order:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
    get:
      summary: List Sales Channels in Display Order
      description: |
        Returns every sales channel that belongs to the organisation, sorted
        by the organisation-wide display order (ascending). Use this
        endpoint when you need the channels in the order they should be
        rendered in a UI picker; use `GET /shop/organisations/{organisationId}/sales-channels`
        when you want a paginated list.

        Requires the `RESERVATIONS_VIEW` permission on a site under the
        organisation.
      operationId: listOrganisationSalesChannelsOrder
      tags:
        - Organisations
      responses:
        '200':
          description: The ordered sales channels.
          content:
            application/json:
              schema:
                title: ListOrganisationSalesChannelsOrder
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    description: |
                      Sales channels for the organisation in display order,
                      smallest `order` first.
                    items:
                      $ref: '#/components/schemas/schemas_SalesChannel-2'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update Sales Channels Order
      description: |
        Updates the organisation-wide display order of sales channels by
        supplying the desired sequence of `SalesChannel` IDs. IDs not
        listed retain their previous order relative to one another and are
        appended to the tail.

        Requires the `SHARED_SETTINGS_MANAGE` permission on any site under
        the organisation.
      operationId: updateSalesChannelsOrder
      tags:
        - Organisations
      requestBody:
        $ref: '#/components/requestBodies/UpdateSalesChannelsOrder'
      responses:
        '204':
          description: The sales channel order was updated successfully.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/item-choices/reorder:
    parameters:
      - $ref: '#/components/parameters/packageId'
    post:
      summary: Reorder a package's item choice groups
      description: |
        Reorders the `item_choices` groups on a `Package` to match the
        supplied sequence of group IDs. Pass every existing
        `item_choices[].id` exactly once in the desired display order.

        IDs not included in the `order` array are pushed to the tail in
        their original relative order, so a partial reorder simply moves
        the listed IDs to the front. Unknown IDs are ignored.

        Returns the freshly-sorted `Package`. Requires the
        `SETTINGS_MANAGE` permission on the package's site.
      operationId: actionReorderPackageItemChoices
      tags:
        - Packages
      requestBody:
        $ref: '#/components/requestBodies/ReorderPackageItemChoices'
      responses:
        '200':
          $ref: '#/components/responses/ShowPackage'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/pms/requests/{requestId}/retry:
    parameters:
      - $ref: '#/components/parameters/requestId'
  /shop/practitioner-scheduled-availability:
    get:
      summary: List a practitioner's scheduled availability
      description: |
        Returns the resolved availability windows for one or more
        practitioners over the requested date range. Windows mix
        rota-derived "regular" availability with `CustomAvailabilityRule`
        overrides (which can be either available or explicitly
        unavailable); the response carries an `availability_type` flag so
        consumers can tell them apart.

        Use either a date-range (`date_from` / `date_to`, inclusive of
        whole days in the practitioner's timezone) or a date-time range
        (`date_time_from` / `date_time_to`, half-open) — supply one pair
        or the other, not both.

        Practitioners are processed in the order they appear in
        `practitioner_ids`; the response is sorted by start time within
        each practitioner. Returns an empty list if no practitioners were
        supplied.

        Requires the `view` ability on every supplied practitioner. A
        single forbidden practitioner aborts the request with `403`.
      operationId: listPractitionerScheduledAvailability
      tags:
        - Practitioners
      parameters:
        - $ref: '#/components/parameters/parameters_practitionerIds'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_dateTimeFrom-2'
        - $ref: '#/components/parameters/parameters_dateTimeTo-2'
      responses:
        '200':
          description: The resolved practitioner availability windows.
          content:
            application/json:
              schema:
                title: ListPractitionerScheduledAvailability
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ScheduledAvailabilityWindow'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/queued-jobs/{queuedJobId}:
    parameters:
      - $ref: '#/components/parameters/queuedJobId'
    get:
      summary: Get a queued job
      description: |
        Returns the status and output of a Trybe-internal background job
        that was previously kicked off via a queue-issuing endpoint (e.g.
        `queueExport`, `queueImportVouchers`, the practitioner-occupancy
        queue endpoints, voucher-code bulk creation).

        Poll this endpoint to watch a job progress from `pending` →
        `in_progress` → `complete`/`failed`. Once `status` is `complete`,
        `output` contains the per-job result envelope (a list of created
        records, a signed download URL, error rows, etc., depending on the
        job).

        Requires the `view` ability on the `QueuedJob` — typically granted
        to the user who originally enqueued the job.
      operationId: getQueuedJob
      tags:
        - Meta
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/room-reservation-types/{roomReservationTypeId}/copy:
    parameters:
      - $ref: '#/components/parameters/roomReservationTypeId'
    post:
      summary: Duplicate a room reservation type
      description: |
        Creates a copy of an existing `TableReservationType` (exposed here
        under the `room-reservation-types` URL alias for legacy callers)
        with the supplied fields overlaid on top of the source. Useful when
        seeding a near-identical offering off an existing one rather than
        rebuilding it from scratch.

        Fields omitted from the body are inherited from the source verbatim.
        The new reservation type is created under the same site and
        organisation as the original; pass `site_id` in the body to override.

        Requires the `create` ability on `TableReservationType` for the
        target site.
      operationId: copyRoomReservationType
      tags:
        - TableReservationTypes
      requestBody:
        $ref: '#/components/requestBodies/CopyRoomReservationType'
      responses:
        '200':
          $ref: '#/components/responses/TableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/room-reservation-types/{roomReservationTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/roomReservationTypeId'
    post:
      summary: Restore a room reservation type
      description: |
        Restores a previously archived (soft-deleted) `TableReservationType`
        via the `room-reservation-types` URL alias kept for legacy callers.
        The reservation type returns to its pre-deletion state with every
        associated `IntegrationConfig` and option group intact.

        Requires the `restore` ability on the underlying reservation type.
        No request body.
      operationId: restoreRoomReservationType
      tags:
        - TableReservationTypes
      responses:
        '200':
          $ref: '#/components/responses/TableReservationTypeResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/room-scheduled-availability:
    get:
      summary: List a room's scheduled availability
      description: |
        Returns the resolved availability windows for one or more rooms
        over the requested date range. Rooms derive their schedule from
        the parent site's bookable hours plus any per-room
        custom-availability rules; the response mixes both and tags each
        row with an `availability_type`.

        Use either a date-range (`date_from` / `date_to`) or a date-time
        range (`date_time_from` / `date_time_to`). All date/datetime
        parameters are parsed in the calling site's timezone using the
        `YYYY-MM-DD HH:mm:ss` format (date-only values are also accepted).

        Rooms are processed in the order supplied; the response is sorted
        by start time within each room.

        Requires the `view` ability on every supplied room.
      operationId: listRoomScheduledAvailability
      tags:
        - Rooms
      parameters:
        - $ref: '#/components/parameters/parameters_roomIds-2'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
        - $ref: '#/components/parameters/parameters_dateTimeFrom-2'
        - $ref: '#/components/parameters/parameters_dateTimeTo-2'
      responses:
        '200':
          description: The resolved room availability windows.
          content:
            application/json:
              schema:
                title: ListRoomScheduledAvailability
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ScheduledAvailabilityWindow'
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /brands/{brandId}/email-config:
    parameters:
      - $ref: '#/components/parameters/parameters_brandId-2'
  /customers/check-ins:
    get:
      summary: List Check-ins
      description: |
        Retrieves a list of all check-ins, optionally filtered by customer, site, date range and method.
      tags:
        - CheckIns
      operationId: listCheckIns
      parameters:
        - $ref: '#/components/parameters/customerIdsQuery'
        - $ref: '#/components/parameters/siteIdQuery'
        - $ref: '#/components/parameters/parameters_dateFromQuery'
        - $ref: '#/components/parameters/parameters_dateToQuery'
        - $ref: '#/components/parameters/checkedInAtFromQuery'
        - $ref: '#/components/parameters/checkedInAtToQuery'
        - $ref: '#/components/parameters/methodIdQuery'
        - $ref: '#/components/parameters/methodTypeQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCheckIns'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a Check-in
      description: |
        Records a new check-in for a customer at the given site.
      tags:
        - CheckIns
      operationId: createCheckIn
      requestBody:
        $ref: '#/components/requestBodies/CreateCheckIn'
      responses:
        '201':
          $ref: '#/components/responses/ShowCheckIn'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/check-ins/queue:
    get:
      summary: Queue a Check-ins Report
      description: |
        Retrieves a report of check-ins in CSV format. The report will be generated asynchronously.
      tags:
        - CheckIns
      operationId: queueListCheckIns
      parameters:
        - $ref: '#/components/parameters/customerIdQuery'
        - $ref: '#/components/parameters/siteIdQuery'
        - $ref: '#/components/parameters/parameters_dateFromQuery'
        - $ref: '#/components/parameters/parameters_dateToQuery'
        - $ref: '#/components/parameters/checkedInAtFromQuery'
        - $ref: '#/components/parameters/checkedInAtToQuery'
        - $ref: '#/components/parameters/methodIdQuery'
        - $ref: '#/components/parameters/methodTypeQuery'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/contraindications/{contraindicationId}:
    parameters:
      - $ref: '#/components/parameters/contraindicationIdPath'
  /customers/customers/{customerId}/addresses:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List a Customer's Addresses
      description: |
        Retrieves a paginated list of addresses belonging to the given customer.
      tags:
        - Customers
      operationId: listCustomerAddresses
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerAddresses'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create an Address for a Customer
      description: |
        Creates a new postal address for the given customer.
      tags:
        - Customers
      operationId: createCustomerAddress
      requestBody:
        $ref: '#/components/requestBodies/CreateCustomerAddress'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomerAddress'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/addresses/{addressId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/addressIdPath'
    get:
      summary: Get a Customer Address
      description: |
        Retrieves a specific address belonging to the given customer.
      tags:
        - Customers
      operationId: getCustomerAddress
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerAddress'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Customer Address
      description: |
        Updates an existing address belonging to the given customer.
      tags:
        - Customers
      operationId: updateCustomerAddress
      requestBody:
        $ref: '#/components/requestBodies/UpdateCustomerAddress'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerAddress'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Customer Address
      description: |
        Deletes the given address from the customer.
      tags:
        - Customers
      operationId: deleteCustomerAddress
      responses:
        '204':
          description: The address was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/barcodes:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List Associated Barcodes
      description: |
        Retrieves the barcodes associated with the given customer.
      tags:
        - Customers
      operationId: listCustomerAssociatedBarcodes
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerAssociatedBarcodes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Associate a Barcode with a Customer
      description: |
        Associates the given barcode with the customer. Once associated, the barcode can be used to identify the customer at point-of-sale and kiosk-style integrations.
      tags:
        - Customers
      operationId: createCustomerBarcode
      requestBody:
        $ref: '#/components/requestBodies/AssociateCustomerBarcode'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerAssociatedBarcode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/barcodes/{barcodeId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/barcodeIdPath'
    get:
      summary: Get an Associated Barcode
      description: |
        Retrieves the given barcode associated with the customer.
      tags:
        - Customers
      operationId: getCustomerAssociatedBarcode
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerAssociatedBarcode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Disassociate a Barcode from a Customer
      description: |
        Removes the association between the given barcode and customer.
      tags:
        - Customers
      operationId: deleteCustomerBarcode
      responses:
        '204':
          description: The barcode was successfully disassociated
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/bill:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
  /customers/customers/{customerId}/contraindications:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
  /customers/customers/{customerId}/credits:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List Customer Credits
      description: |
        Retrieves a paginated list of credits issued to the given customer.
      tags:
        - CustomerCredits
      operationId: listCustomerCredits
      parameters:
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/redeemedQuery'
        - $ref: '#/components/parameters/expiredQuery'
        - $ref: '#/components/parameters/revokedQuery'
        - $ref: '#/components/parameters/multiUseQuery'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerCredits'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Issue a Customer Credit
      description: |
        Issues a one-off credit to the customer. Use this endpoint to grant an ad-hoc coupon credit; recurring credits typically come from membership credit rules.
      tags:
        - CustomerCredits
      operationId: createCustomerCredit
      requestBody:
        $ref: '#/components/requestBodies/IssueCustomerCredit'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomerCredit'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/credits/{creditId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/creditIdPath'
    get:
      summary: Get a Customer Credit
      description: |
        Retrieves a single customer credit by its ID.
      tags:
        - CustomerCredits
      operationId: getCustomerCredit
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerCredit'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Revoke a Customer Credit
      description: |
        Revokes the given customer credit so that it can no longer be redeemed. Credits that have already been redeemed cannot be revoked.
      tags:
        - CustomerCredits
      operationId: deleteCustomerCredit
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerCredit'
        '400':
          description: The credit couldn't be revoked
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/labels:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: Get a Customer's Labels
      description: |
        Returns a list of the labels attached to the customer.
      tags:
        - CustomerLabels
      operationId: getCustomerLabels
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerAttachedLabels'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Attach Labels to a Customer
      description: |
        Attaches the given existing labels to the customer. Labels already attached are ignored.
      tags:
        - CustomerLabels
      operationId: createCustomerLabels
      requestBody:
        $ref: '#/components/requestBodies/AttachDetachCustomerLabels'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerAttachedLabels'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Detach Labels from a Customer
      description: |
        Detaches the given labels from the customer. Labels that are not currently attached are ignored.
      tags:
        - CustomerLabels
      operationId: deleteCustomerLabels
      requestBody:
        $ref: '#/components/requestBodies/AttachDetachCustomerLabels'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerAttachedLabels'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/marketing-preferences:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List a Customer's Marketing Preferences
      description: |
        Returns the marketing preferences that exist in the customer's organisation along with the customer's opt-in state for each.
      tags:
        - CustomerMarketingPreferences
      operationId: listCustomerMarketingPreferences
      parameters:
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerMarketingPreferences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/marketing-preferences/{marketingPreferenceId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/marketingPreferenceIdPath'
    get:
      summary: Get a Customer's Marketing Preference
      description: |
        Returns the customer's opt-in state for the given marketing
        preference. If the customer has never been presented with the
        preference, the response describes the implicit opted-out state
        (the preference's id with `opted_in: false`) rather than 404ing.
      tags:
        - CustomerMarketingPreferences
      operationId: getCustomerMarketingPreference
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerMarketingPreference'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Opt a Customer into a Marketing Preference
      description: |
        Opts the customer into the given marketing preference.
      tags:
        - CustomerMarketingPreferences
      operationId: actionMarketingPreferenceOptIn
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerMarketingPreference'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Opt a Customer out of a Marketing Preference
      description: |
        Opts the customer out of the given marketing preference.
      tags:
        - CustomerMarketingPreferences
      operationId: actionMarketingPreferenceOptOut
      responses:
        '204':
          description: The customer was opted out of the marketing preference
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/notes:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    get:
      summary: List Customer Notes
      description: |
        Returns the notes that have been recorded against the given customer.
      tags:
        - CustomerNotes
      operationId: listNotes
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerNotes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create a Customer Note
      description: |
        Records a new note against the given customer.
      tags:
        - CustomerNotes
      operationId: createNote
      requestBody:
        $ref: '#/components/requestBodies/CreateCustomerNote'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomerNote'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/notes/{noteId}:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/noteIdPath'
    put:
      summary: Update a Customer Note
      description: |
        Updates the contents of an existing customer note.
      tags:
        - CustomerNotes
      operationId: updateNote
      requestBody:
        $ref: '#/components/requestBodies/UpdateCustomerNote'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerNote'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Customer Note
      description: |
        Deletes the given customer note.
      tags:
        - CustomerNotes
      operationId: deleteNote
      responses:
        '204':
          description: The note was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/{customerId}/set-password-url:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
    post:
      summary: Generate a Set-Password URL
      description: |
        Generates a one-time URL that can be sent to the customer for them to set or reset their password. The token included in the URL is valid for a limited time.
      tags:
        - Customers
      operationId: createSetPasswordUrl
      responses:
        '200':
          description: The URL to set the password was successfully generated
          content:
            application/json:
              schema:
                title: SetCustomerPassword
                type: object
                additionalProperties: false
                properties:
                  data:
                    title: SetCustomerPasswordData
                    type: object
                    additionalProperties: false
                    properties:
                      token:
                        type: string
                        description: The token required to set the customer's password
                      url:
                        type: string
                        format: url
                        description: The URL which should be visited to set the customer's password
                    required:
                      - token
                      - url
                required:
                  - data
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/barcode-search/{code}:
    parameters:
      - $ref: '#/components/parameters/parameters_code-6'
      - $ref: '#/components/parameters/parameters_siteIdQuery'
    get:
      summary: Search for a Customer by Barcode
      description: |
        Looks up a customer by an associated barcode payload (or by their customer ID).
      tags:
        - Customers
      operationId: getCustomerByBarcode
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/customers/queue:
    get:
      summary: Queue a Report of Customers
      description: |
        Retrieves a report of customers in CSV format. The report will be generated asynchronously.
      tags:
        - Customers
      operationId: queueListCustomers
      parameters:
        - $ref: '#/components/parameters/parameters_query-8'
        - $ref: '#/components/parameters/parameters_email'
        - $ref: '#/components/parameters/organisation_id'
        - $ref: '#/components/parameters/brand_id'
        - $ref: '#/components/parameters/membership_number'
        - $ref: '#/components/parameters/name'
        - $ref: '#/components/parameters/phone'
        - $ref: '#/components/parameters/membership'
        - $ref: '#/components/parameters/membership_created_at_from'
        - $ref: '#/components/parameters/membership_created_at_to'
        - $ref: '#/components/parameters/membership_type_id'
        - $ref: '#/components/parameters/membership_rate_id'
        - $ref: '#/components/parameters/marketing_opt_in'
        - $ref: '#/components/parameters/label_ids'
        - $ref: '#/components/parameters/created_at_from'
        - $ref: '#/components/parameters/created_at_to'
        - $ref: '#/components/parameters/updated_at_from'
        - $ref: '#/components/parameters/updated_at_to'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/labels:
    get:
      summary: List Labels
      description: |
        Retrieves a list of all the labels set up against the authenticated user's organisation.
      tags:
        - Labels
      operationId: listLabels
      parameters:
        - $ref: '#/components/parameters/archivedQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListLabels'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a Label
      description: |
        Creates a new `Label` on the authenticated user's organisation.
        Labels are then available to attach to any `Customer` in the
        organisation for ad-hoc segmentation in reports and Customer
        Hub searches.
      tags:
        - Labels
      operationId: createLabel
      requestBody:
        $ref: '#/components/requestBodies/CreateLabel'
      responses:
        '201':
          $ref: '#/components/responses/ShowLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/labels/{labelId}:
    parameters:
      - $ref: '#/components/parameters/labelIdPath'
    get:
      summary: Get a Label
      description: |
        Retrieves details about the given label.
      tags:
        - Labels
      operationId: getLabel
      responses:
        '200':
          $ref: '#/components/responses/ShowLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a Label
      description: |
        Updates the given `Label`. The change applies retroactively
        everywhere the label is currently attached — there is no
        versioning, so renaming a label changes how it appears against
        every customer that already carries it.
      tags:
        - Labels
      operationId: updateLabel
      requestBody:
        $ref: '#/components/requestBodies/UpdateLabel'
      responses:
        '200':
          $ref: '#/components/responses/ShowLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a Label
      description: |
        Soft-deletes the given label.
      tags:
        - Labels
      operationId: deleteLabel
      responses:
        '204':
          description: The label was successfully soft-deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/labels/{labelId}/restore:
    parameters:
      - $ref: '#/components/parameters/labelIdPath'
    post:
      summary: Restore a Label
      description: |
        Restores a soft-deleted label.
      tags:
        - Labels
      operationId: restoreLabel
      responses:
        '200':
          $ref: '#/components/responses/ShowLabel'
        '400':
          description: The label could not be restored
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-charges/{membershipChargeId}:
    parameters:
      - $ref: '#/components/parameters/membershipChargeId'
    get:
      summary: Retrieve a MembershipCharge
      description: |
        Use this endpoint to retrieve a single `MembershipCharge` by its ID.
      tags:
        - MembershipCharges
      operationId: getMembershipCharge
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipCharge'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-charges/{membershipChargeId}/receipt:
    parameters:
      - $ref: '#/components/parameters/membershipChargeId'
    get:
      summary: Download the receipt for this charge
      description: |
        Returns a temporary `download_url` for the PDF receipt of the given `MembershipCharge`.
        The URL expires 10 minutes after it's issued.
      tags:
        - MembershipCharges
      operationId: getReceipt
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipChargeReceipt'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-charges/{membershipChargeId}/refund:
    parameters:
      - $ref: '#/components/parameters/membershipChargeId'
    post:
      summary: Refund a MembershipCharge
      description: |
        Initiates a refund for some or all of the amount on a `MembershipCharge`. The refund
        is processed asynchronously through the payment processor.
      tags:
        - MembershipCharges
      operationId: actionRefundMembershipCharge
      requestBody:
        $ref: '#/components/requestBodies/RefundMembershipCharge'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipCharge'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-rates/{membershipRateId}/restore:
    parameters:
      - $ref: '#/components/parameters/membershipRateId'
    post:
      summary: Restore a MembershipRate
      description: |
        Restores an archived `MembershipRate` so it can once again be used for new memberships.
      tags:
        - MembershipRates
      operationId: restoreMembershipRate
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipRate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-rates/{membershipRateId}/locale-strings/{locale}:
    parameters:
      - $ref: '#/components/parameters/membershipRateId'
      - $ref: '#/components/parameters/locale'
    get:
      summary: Retrieve locale strings for a MembershipRate
      description: Returns the localised `name` for the given locale.
      operationId: getMembershipRateLocaleStrings
      tags:
        - MembershipRates
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipRateLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    put:
      summary: Update locale strings for a MembershipRate
      description: Sets the localised `name` for the given locale. Pass `null` to clear the translation and fall back to the default name.
      operationId: updateMembershipRateLocaleStrings
      tags:
        - MembershipRates
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipRateLocaleStrings'
      responses:
        '200':
          $ref: '#/components/responses/UpdateMembershipRateLocaleStrings'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/membership-rates/{rateId}:
    parameters:
      - $ref: '#/components/parameters/parameters_rateId'
    get:
      summary: Retrieve a MembershipRate
      description: |
        Use this endpoint to retrieve a single `MembershipRate` by its ID.
      tags:
        - MembershipRates
      operationId: getMembershipRate
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipRate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a MembershipRate
      description: |
        Update an existing `MembershipRate`. Only fields included in the request body will be
        changed.
      tags:
        - MembershipRates
      operationId: updateMembershipRate
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipRate'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipRate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Archive a MembershipRate
      description: |
        Archives a `MembershipRate`. Archived rates cannot be used for new memberships but
        existing memberships continue to bill at the rate.
      tags:
        - MembershipRates
      operationId: deleteMembershipRate
      responses:
        '204':
          description: The membership rate was successfully archived.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/membership-rates/{rateId}/totals:
    parameters:
      - $ref: '#/components/parameters/parameters_rateId'
    get:
      summary: Get totals for a MembershipRate
      description: |
        Returns a breakdown of the total amount a customer will pay to start a membership at
        this rate over the given period, including any joining fee, pro-rata fee and recurring
        monthly fee.
      tags:
        - MembershipRates
      operationId: getTotalsForMembershipRate
      parameters:
        - $ref: '#/components/parameters/totalsStartDate'
        - $ref: '#/components/parameters/totalsEndDate'
        - $ref: '#/components/parameters/totalsSource'
        - $ref: '#/components/parameters/acceptLanguage'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipRateTotals'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/add-payment:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Add a manual payment
      description: |
        Records a manual payment against the membership. Use this when a payment for the
        membership has been collected outside of Trybe (e.g. cash or bank transfer) and you
        want to mark the current billing period as paid.
      tags:
        - Memberships
      operationId: actionAddManualPayment
      requestBody:
        $ref: '#/components/requestBodies/AddManualPayment'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/memberships/{membershipId}/cancel:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Cancel a membership
      description: |
        Cancels the given `Membership`. Cancelling a membership marks it as no longer active
        and stops further billing.
      tags:
        - Memberships
      operationId: actionCancelMembership
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/checkout-session/direct-debit:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Collect Direct Debit details
      description: |
        This endpoint is used to create the Stripe Checkout session for collecting bank details
        for a Direct Debit mandate. A `stripe_session_id` is returned which can be passed into
        the Stripe.js SDK to redirect the user to the checkout.
      tags:
        - Memberships
      operationId: createDirectDebitCheckoutSession
      responses:
        '200':
          $ref: '#/components/responses/ShowStripeCheckoutSession'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/checkout-session/joining-fee:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Collect a joining fee
      description: |
        This endpoint is used to create the Stripe Checkout session for collecting a joining fee
        as well as any pro-rata fees. A `stripe_session_id` is returned which can be passed into
        the Stripe.js SDK to redirect the user to the checkout.
      tags:
        - Memberships
      operationId: createJoiningFeeCheckoutSession
      responses:
        '200':
          $ref: '#/components/responses/ShowStripeCheckoutSession'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/confirm:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Confirm a membership
      description: |
        When a membership is created through the self-signup flow, it first goes
        into the "reserved" stage. This means the client hasn't completed their
        signup yet, and the basket needs to be completed. Calling this endpoint
        sets the status to `needs_attention` if a mandate is required, or
        `active` if not.
      tags:
        - Memberships
      operationId: actionConfirmMembership
      parameters:
        - $ref: '#/components/parameters/onBehalfOf'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/issue-credits:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Issue credits for a membership
      description: |
        Queues a job that issues credits to the members of the given membership, according to
        the membership's credit rules. Credits are issued asynchronously.
      tags:
        - Memberships
      operationId: actionIssueMembershipCredits
      responses:
        '204':
          description: The request to issue credits was successful and is being processed.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/members:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    get:
      summary: Retrieve a list of members for a membership
      description: |
        Returns the list of `MembershipMember`s on the given membership, including their
        customer record, membership number and lead-member status.
      tags:
        - Memberships
      operationId: listMembershipMembers
      responses:
        '200':
          $ref: '#/components/responses/ListMembershipMembers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add a member to a membership
      description: |
        Adds an existing `Customer` to the given `Membership` as an additional member.
        The customer is identified by their `customer_id`.
      tags:
        - Memberships
      operationId: createMembershipMember
      requestBody:
        $ref: '#/components/requestBodies/AddMembershipMember'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipMember'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/memberships/{membershipId}/members/{customerId}:
    parameters:
      - $ref: '#/components/parameters/membershipId'
      - $ref: '#/components/parameters/memberCustomerId'
    delete:
      summary: Remove a member from a membership
      description: |
        Removes the given customer from the given `Membership`. The customer's record is
        preserved; only the link between the customer and the membership is removed.
      tags:
        - Memberships
      operationId: deleteMembershipMember
      responses:
        '204':
          description: The member was successfully removed from the membership.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/next-billing-details:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    get:
      summary: Get the next billing details for a membership
      description: |
        Returns the next billing date and amount for the given `Membership`. If the membership
        will not be active on the next billing date, the date and amount will be `null`.
      tags:
        - Memberships
      operationId: getNextBillingDetails
      responses:
        '200':
          $ref: '#/components/responses/ShowNextBillingDetails'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/regenerate-charges:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Regenerate pending charges for a membership
      description: |
        Regenerates pending charges for the given `Membership`. Any pending charges are
        discarded and new ones are created based on the current rate and billing schedule.
      tags:
        - Memberships
      operationId: actionRegenerateMembershipCharges
      responses:
        '204':
          description: The request to regenerate charges was successful and is being processed.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/report-membership-setup-fee-chargeback:
    parameters:
      - $ref: '#/components/parameters/membershipId'
  /customers/memberships/{membershipId}/request-mandate:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Send the mandate request email
      description: |
        Sends the Direct Debit mandate request email to the lead member of the membership.
        The email contains a link to a Stripe Checkout session for collecting the bank details.

        Returns a `400` if the membership doesn't require a mandate - the status must be
        `needs_dd_mandate` or `needs_attention` for this endpoint to send the email.
      tags:
        - Memberships
      operationId: actionRequestMandate
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/retry-payment:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Retry the payment for a membership
      description: |
        Retries the most recent failed payment for the given `Membership`.

        Returns a `400` if the payment couldn't be retried. This can happen if the membership
        already has a processing payment, or the billing date is in the future, or the
        membership is not in the `needs_attention` status with an attention reason of `payment_failed`.
      tags:
        - Memberships
      operationId: actionRetryPayment
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/send-confirmation-email:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Send a confirmation email for a membership
      description: |
        Sends (or re-sends) the membership signup confirmation email to the lead member.
        The email is dispatched asynchronously.
      tags:
        - Memberships
      operationId: actionSendMembershipConfirmationEmail
      responses:
        '204':
          description: The request to send a confirmation email was successful and is being processed.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/subsequent-billing-date:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    get:
      summary: Get the subsequent billing date for a membership
      description: |
        Returns the subsequent billing date for the given `Membership` - i.e. the billing date
        after `next_billing_date`. If the membership will not be active on the subsequent
        billing date, the date will be `null`.
      tags:
        - Memberships
      operationId: getSubsequentBillingDate
      responses:
        '200':
          $ref: '#/components/responses/ShowSubsequentBillingDate'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/{membershipId}/subsequent-billing-details:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    get:
      summary: Get the subsequent billing details for a membership
      description: |
        Returns the subsequent billing date and amount for the given `Membership` - i.e. the
        billing event after `next_billing_date`. If the membership will not be active on the
        subsequent billing date, the date and amount will be `null`.
      tags:
        - Memberships
      operationId: getSubsequentBillingDetails
      responses:
        '200':
          $ref: '#/components/responses/ShowSubsequentBillingDetails'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/memberships/queue:
    get:
      summary: Queue a report of memberships
      description: |
        Retrieves a report of memberships in CSV format. The report will be generated asynchronously.
      tags:
        - Memberships
      operationId: queueListMemberships
      parameters:
        - $ref: '#/components/parameters/parameters_customerId'
        - $ref: '#/components/parameters/parameters_siteId-52'
        - $ref: '#/components/parameters/parameters_status-10'
        - $ref: '#/components/parameters/membershipTypeIdDeprecated'
        - $ref: '#/components/parameters/parameters_membershipTypeIds-2'
        - $ref: '#/components/parameters/membershipRateIds'
        - $ref: '#/components/parameters/parameters_createdAtFrom-2'
        - $ref: '#/components/parameters/parameters_createdAtTo-2'
        - $ref: '#/components/parameters/nextBillingDateFrom'
        - $ref: '#/components/parameters/nextBillingDateTo'
        - $ref: '#/components/parameters/endDateFrom'
        - $ref: '#/components/parameters/endDateTo'
        - $ref: '#/components/parameters/attentionReason'
        - $ref: '#/components/parameters/parameters_manualPayments-2'
        - $ref: '#/components/parameters/membershipNumber'
        - $ref: '#/components/parameters/externalRef'
        - $ref: '#/components/parameters/parameters_billingFrequency-2'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/my-account:
    get:
      summary: Get My Account Details
      description: |
        Returns base details about the currently authenticated customer (the holder of the bearer customer token).
      tags:
        - MyAccount
      operationId: getMyAccountDetails
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomer'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/my-account/charges:
    get:
      summary: Get My Account Charges
      description: |
        Returns the membership charges that have been billed to the authenticated customer.
      tags:
        - MyAccount
      operationId: listMyAccountCharges
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountCharges'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/my-account/credits:
    get:
      summary: Get My Account Credits
      description: |
        Returns the unredeemed, unexpired credits available to the authenticated customer.

        By default, only credits which haven't been redeemed and haven't expired are shown. Use the query parameters to include redeemed and/or expired credits. Revoked credits are never returned on this endpoint.
      tags:
        - MyAccount
      operationId: listMyAccountCredits
      parameters:
        - $ref: '#/components/parameters/redeemed'
        - $ref: '#/components/parameters/expired'
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountCredits'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/my-account/marketing-preferences:
    get:
      summary: Get My Account Marketing Preferences
      description: |
        Returns the marketing preferences available to the authenticated customer along with the opt-in state for each.
      tags:
        - MyAccount
      operationId: listMyAccountMarketingPreferences
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountMarketingPreferences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/my-account/marketing-preferences/{marketingPreferenceId}:
    parameters:
      - $ref: '#/components/parameters/parameters_marketingPreferenceIdPath'
    post:
      summary: Opt Into a Marketing Preference (My Account)
      description: |
        Opts the authenticated customer into the given marketing preference.
      tags:
        - MyAccount
      operationId: actionMyAccountMarketingPreferenceOptIn
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountMarketingPreferences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Opt Out of a Marketing Preference (My Account)
      description: |
        Opts the authenticated customer out of the given marketing preference.
      tags:
        - MyAccount
      operationId: actionMyAccountMarketingPreferenceOptOut
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountMarketingPreferences'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/my-account/memberships:
    get:
      summary: Get My Account Memberships
      description: |
        Returns the memberships held by the authenticated customer.
      tags:
        - MyAccount
      operationId: listMyAccountMemberships
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountMemberships'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/my-account/payment-methods:
    get:
      summary: Get My Account Payment Methods
      description: |
        Returns the payment methods saved against the authenticated customer.
      tags:
        - MyAccount
      operationId: listMyAccountPaymentMethods
      responses:
        '200':
          $ref: '#/components/responses/ListMyAccountPaymentMethods'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/my-subscriptions:
    get:
      summary: List subscriptions for the current user
      description: |
        Lists the authenticated user's `Subscription`s. A `Subscription` is the user's opt-in
        to receive a particular notification (e.g. failed payment, expiring membership) for a
        specific `Site`.
      tags:
        - Subscriptions
      operationId: listSubscriptions
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-74'
      responses:
        '200':
          $ref: '#/components/responses/ListSubscriptions'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a new subscription
      description: |
        Subscribes the authenticated user to a new notification type for a given site.
      tags:
        - Subscriptions
      operationId: createSubscription
      requestBody:
        $ref: '#/components/requestBodies/CreateSubscription'
      responses:
        '201':
          $ref: '#/components/responses/ShowSubscription'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/my-subscriptions/{subscriptionId}:
    parameters:
      - $ref: '#/components/parameters/subscriptionId'
    delete:
      summary: Delete a subscription
      description: |
        Unsubscribes the authenticated user from the given `Subscription`.
      tags:
        - Subscriptions
      operationId: deleteSubscription
      responses:
        '204':
          description: The subscription was successfully deleted.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/payment-methods/{paymentMethodId}:
    parameters:
      - $ref: '#/components/parameters/paymentMethodId'
    get:
      summary: Get a payment method
      description: |
        Returns the stored details for the given payment method —
        processor, type, masked last-4, status, and timestamps. The
        bearer token must have `CUSTOMERS_VIEW` for the brand that
        owns the underlying customer.
      tags:
        - PaymentMethods
      operationId: getPaymentMethod
      responses:
        '200':
          $ref: '#/components/responses/ShowPaymentMethod'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    delete:
      summary: Delete a payment method
      description: |
        Deletes a payment method belonging to a customer. Once deleted, the payment method can
        no longer be used for new charges.
      tags:
        - PaymentMethods
      operationId: deletePaymentMethod
      responses:
        '204':
          description: The payment method was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/signup-tokens:
    get:
      summary: List SignupTokens
      description: |
        Lists every `SignupToken` you are authorised to see. Tokens are used to permit a customer
        to sign up to a private `MembershipType` or non-default `MembershipRate`.
      tags:
        - SignupTokens
      operationId: listSignupTokens
      responses:
        '200':
          $ref: '#/components/responses/ListSignupTokens'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a SignupToken
      description: |
        Use this endpoint to create a new `SignupToken`. The token is bound to a `MembershipType`
        and optionally to a non-default `MembershipRate`. You can pre-populate the customer's name
        and email, and cap how many times the token can be used.
      tags:
        - SignupTokens
      operationId: createSignupToken
      requestBody:
        $ref: '#/components/requestBodies/CreateSignupToken'
      responses:
        '201':
          $ref: '#/components/responses/ShowSignupToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/signup-tokens/{signupTokenId}:
    parameters:
      - $ref: '#/components/parameters/signupTokenId'
    get:
      summary: Retrieve a SignupToken
      description: |
        Use this endpoint to retrieve a single `SignupToken` by its ID.
      tags:
        - SignupTokens
      operationId: getSignupToken
      responses:
        '200':
          $ref: '#/components/responses/ShowSignupToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a SignupToken
      description: |
        Update an existing `SignupToken`. Only fields included in the request body will be changed.
      tags:
        - SignupTokens
      operationId: updateSignupToken
      requestBody:
        $ref: '#/components/requestBodies/UpdateSignupToken'
      responses:
        '200':
          $ref: '#/components/responses/ShowSignupToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a SignupToken
      description: |
        Soft-deletes a `SignupToken` so that it can no longer be used. The token can be restored
        with the `restoreSignupToken` endpoint.
      tags:
        - SignupTokens
      operationId: deleteSignupToken
      responses:
        '200':
          $ref: '#/components/responses/ShowSignupToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/signup-tokens/{signupTokenId}/restore:
    parameters:
      - $ref: '#/components/parameters/signupTokenId'
    post:
      summary: Restore a deleted SignupToken
      description: |
        Restores a soft-deleted `SignupToken` so that it can be used again.
      tags:
        - SignupTokens
      operationId: restoreSignupToken
      responses:
        '200':
          $ref: '#/components/responses/ShowSignupToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/sites/{siteId}/gantner/device-logs:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/parameters_deviceId'
      - $ref: '#/components/parameters/dateFromQuery'
      - $ref: '#/components/parameters/dateToQuery'
      - $ref: '#/components/parameters/logType'
      - $ref: '#/components/parameters/perPageParam'
      - $ref: '#/components/parameters/pageParam'
  /customers/sites/{siteId}/gantner/devices/{deviceId}/entry-rules:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/deviceId'
  /customers/sites/{siteId}/gantner/devices/{deviceId}/entry-rules/{entryRuleId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
      - $ref: '#/components/parameters/deviceId'
      - $ref: '#/components/parameters/entryRuleId'
  /customers/sites/{siteId}/mobile-pass-customisation:
    parameters:
      - $ref: '#/components/parameters/parameters_siteId-16'
    get:
      summary: Retrieve the mobile pass customisation
      description: |
        Retrieves the mobile pass customisation for the given site. The customisation controls
        the visual appearance of digital wallet passes (Apple Wallet / Google Wallet) issued to
        members.
      tags:
        - Sites
      operationId: getMobilePassCustomisation
      responses:
        '200':
          $ref: '#/components/responses/ShowMobilePassCustomisation'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Update the mobile pass customisation
      description: |
        Updates the mobile pass customisation for the given site, including the icon, logo,
        strip image and colour scheme. The `icon_id` is required; the other media references
        are optional.
      tags:
        - Sites
      operationId: updateMobilePassCustomisation
      requestBody:
        $ref: '#/components/requestBodies/UpdateMobilePassCustomisation'
      responses:
        '200':
          $ref: '#/components/responses/ShowMobilePassCustomisation'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /grouped-notifications:
    get:
      summary: Get a grouped summary of notifications
      description: |
        Returns the in-product notifications for the currently
        authenticated user, grouped by notification type. Use this view
        to render the notification tray's collapsed-by-default layout —
        `notifications` within each group contains the individual
        records, and the top-level `meta` exposes read/unread counts and
        per-type totals.
      operationId: listGroupedNotifications
      tags:
        - Notifications
      parameters:
        - $ref: '#/components/parameters/requiredSiteIdQuery'
      responses:
        '200':
          description: Notifications were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListGroupedNotifications
                type: object
                additionalProperties: false
                required:
                  - data
                  - meta
                properties:
                  data:
                    description: The list of notification groups.
                    type: array
                    items:
                      type: object
                      title: GroupedNotificationGroup
                      additionalProperties: false
                      properties:
                        type:
                          type: string
                          description: The notification type discriminator the group is for.
                        title:
                          type: string
                          description: A human-readable title for the group.
                          example: An order was created by rezlynx
                        notifications:
                          type: array
                          items:
                            $ref: '#/components/schemas/Notification'
                        read:
                          type: boolean
                          description: Whether every notification in the group has been read.
                          example: true
                        count:
                          type: integer
                          description: The number of notifications in the group.
                        date:
                          type: string
                          format: date-time
                          description: The date of the most recent notification in the group.
                  meta:
                    type: object
                    title: GroupedNotificationsMeta
                    additionalProperties: false
                    properties:
                      total:
                        type: integer
                        description: The total number of notifications across every group.
                      counts:
                        title: GroupedNotificationsCounts
                        type: object
                        description: A map of notification type to count.
                        additionalProperties: true
                        properties: {}
                      total_read:
                        description: The number of notifications that have been read.
                        type: integer
                        example: 1
                      total_unread:
                        description: The number of notifications that have not been read.
                        type: integer
                        example: 1
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /inventory/adjustments:
    get:
      summary: List inventory adjustments
      description: |
        Returns the paginated list of stock adjustments — positive or
        negative changes to product quantities — across the caller's
        visible scope, optionally filtered by site.
      operationId: listInventoryAdjustments
      tags:
        - InventoryAdjustments
      parameters:
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryAdjustments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a new inventory adjustment
      description: |
        Records a stock adjustment — a positive or negative change to
        the quantity of a product at a location. The adjustment is
        timestamped and attributed to the calling user for audit.
      operationId: createInventoryAdjustment
      tags:
        - InventoryAdjustments
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryAdjustment'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryAdjustment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/locations:
    get:
      summary: List inventory locations
      description: |
        Returns the paginated list of inventory locations the caller can
        see, optionally filtered by site. Use this to populate the
        location picker on stock-count and adjustment flows.
      operationId: listInventoryLocations
      tags:
        - InventoryLocations
      parameters:
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryLocations'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a new inventory location
      description: |
        Creates a new inventory location at the given site. Locations
        are the buckets against which stock counts and adjustments are
        recorded.
      operationId: createInventoryLocation
      tags:
        - InventoryLocations
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryLocation'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryLocation'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/locations/{locationId}:
    parameters:
      - $ref: '#/components/parameters/locationId'
    get:
      summary: Get the details of a single inventory location
      description: |
        Returns the canonical record for a single inventory location.
      operationId: getInventoryLocation
      tags:
        - InventoryLocations
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryLocation'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an existing inventory location
      description: |
        Updates the display name of an inventory location. Stock counts
        and adjustments already recorded against the location are
        unaffected.
      operationId: updateInventoryLocation
      tags:
        - InventoryLocations
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryLocation'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryLocation'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete an inventory location
      description: |
        Soft-deletes an inventory location so it no longer appears in
        location pickers or new stock movements. Historical stock
        adjustments, stocktakes and order items already attached to the
        location remain intact and continue to reference the deleted
        record by ID.
      operationId: deleteInventoryLocation
      tags:
        - InventoryLocations
      responses:
        '204':
          description: The inventory location was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/locations/{locationId}/adjustments:
    parameters:
      - $ref: '#/components/parameters/locationId'
    get:
      summary: List adjustments for a single inventory location
      description: |
        Returns the paginated list of stock adjustments scoped to a
        single inventory location. Use this for a per-location audit
        trail of stock movement.
      operationId: listInventoryLocationAdjustments
      tags:
        - InventoryLocations
      parameters:
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryAdjustments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/products/{productId}/suppliers:
    parameters:
      - $ref: '#/components/parameters/parameters_productId'
    get:
      summary: List suppliers of an Inventory Product
      description: |
        Returns the paginated list of suppliers associated with a single
        inventory product. Each entry describes the supplier-side ID
        (e.g. their SKU), the default order quantity, and the unit
        price.
      operationId: listInventoryProductSuppliers
      tags:
        - InventoryProducts
      parameters:
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/pageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListInventoryProductSuppliers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add a supplier to an Inventory Product
      description: |
        Associates a supplier with a product, capturing the supplier's
        SKU, default order quantity, and unit price. Multiple suppliers
        can be associated with the same product.
      operationId: createInventoryProductSupplierLink
      tags:
        - InventoryProducts
      requestBody:
        $ref: '#/components/requestBodies/CreateInventoryProductSupplierLink'
      responses:
        '201':
          $ref: '#/components/responses/ShowInventoryProductSupplierLink'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/products/{productId}/suppliers/{supplierProductId}:
    parameters:
      - $ref: '#/components/parameters/parameters_productId'
      - $ref: '#/components/parameters/supplierProductId'
    get:
      summary: Get a single Inventory Product Supplier
      description: |
        Returns the details of a single supplier-product association,
        including the supplier's SKU, the default order quantity, and
        the unit price.
      operationId: getInventoryProductSupplierLink
      tags:
        - InventoryProducts
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProductSupplierLink'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update an Inventory Product Supplier
      description: |
        Updates the supplier-product association — typically to adjust
        the supplier's SKU or default order quantity. The supplier
        itself cannot be reassigned; delete and recreate the
        association if you need to switch suppliers.
      operationId: updateInventoryProductSupplierLink
      tags:
        - InventoryProducts
      requestBody:
        $ref: '#/components/requestBodies/UpdateInventoryProductSupplierLink'
      responses:
        '200':
          $ref: '#/components/responses/ShowInventoryProductSupplierLink'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove a supplier from an Inventory Product
      description: |
        Removes a single supplier-product association. The supplier and
        product records themselves are unaffected.
      operationId: deleteInventoryProductSupplierLink
      tags:
        - InventoryProducts
      responses:
        '204':
          description: The supplier-product association was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/queued-jobs/{queuedJobId}:
    parameters:
      - $ref: '#/components/parameters/parameters_queuedJobId'
    get:
      summary: Get the details of an inventory queued job
      description: |
        Returns the status and output of an inventory background job
        that was previously kicked off via a queue-issuing endpoint
        (e.g. stock-on-hand or stock-adjustment exports, stock-take
        posting). Poll this endpoint until `status` transitions to
        `complete` or `failed`; `output` then contains the per-job
        result envelope.
      operationId: getInventoryQueuedJob
      tags:
        - InventoryProducts
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes/{stockTakeId}/items-v2:
    parameters:
      - $ref: '#/components/parameters/stockTakeId'
    get:
      summary: List the items of a stock take (v2)
      description: |
        Returns the items of a stocktake with v2 totals and filters. Use
        `query`, `status`, and the category/supplier/brand filters to
        drill into a specific slice of the stocktake while it's in
        progress. Compared to the v1 list (`listStockTakeItems`), the
        v2 response surfaces additional totals: total items, counted,
        uncounted, total adjustment value, and currency.
      operationId: listStockTakeItemsV2
      tags:
        - StockTakes
      parameters:
        - $ref: '#/components/parameters/parameters_categoryIds-6'
        - $ref: '#/components/parameters/parameters_supplierIds-3'
        - $ref: '#/components/parameters/parameters_brandIds-6'
        - $ref: '#/components/parameters/parameters_query-20'
        - $ref: '#/components/parameters/parameters_status-15'
      responses:
        '200':
          description: The stock take items were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListStockTakeItemsV2
                type: object
                additionalProperties: false
                required:
                  - data
                  - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/StockTakeItem'
                  meta:
                    type: object
                    title: ListStockTakeItemsV2Meta
                    additionalProperties: false
                    properties:
                      total_items:
                        type: integer
                        description: The total number of items in the stock take.
                        example: 100
                      total_counted:
                        type: integer
                        description: The total number of items counted in the stock take.
                        example: 50
                      total_uncounted:
                        type: integer
                        description: The total number of items uncounted in the stock take.
                        example: 50
                      total_adjustment_value:
                        type: integer
                        description: The value of the total adjustments for the stock take.
                        example: 50
                      currency:
                        type: string
                        description: The currency of the stock take.
                        example: gbp
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /inventory/stock-takes/{stockTakeId}/submit:
    parameters:
      - $ref: '#/components/parameters/stockTakeId'
    post:
      summary: Submit a stock take
      description: |
        Submits the stocktake, locking it from further edits and posting
        the resulting stock adjustments synchronously. Use this instead
        of `createStockTakePosting` when the caller wants the
        adjustments applied immediately rather than via the async queue.
      operationId: actionSubmitStockTake
      tags:
        - StockTakes
      responses:
        '200':
          $ref: '#/components/responses/ShowStockTake'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /feature-flags/{featureFlagKey}:
    parameters:
      - $ref: '#/components/parameters/featureFlagKey'
  /feature-flags/{featureFlagKey}/enable-globally:
    parameters:
      - $ref: '#/components/parameters/featureFlagKey'
  /feature-flags/{featureFlagKey}/disable-globally:
    parameters:
      - $ref: '#/components/parameters/featureFlagKey'
  /feature-flags/{featureFlagKey}/manage-sites:
    parameters:
      - $ref: '#/components/parameters/featureFlagKey'
  /notifications:
    get:
      summary: Get notifications for the authenticated user
      description: |
        Returns the in-product notifications raised for the currently
        authenticated user at the given site, ordered most recent first.
        Use the optional filters to narrow by read status or type.
      operationId: listNotifications
      tags:
        - Notifications
      parameters:
        - $ref: '#/components/parameters/parameters_requiredSiteIdQuery'
        - $ref: '#/components/parameters/readQuery'
        - $ref: '#/components/parameters/typeQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListNotifications'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
  /notifications/{notificationId}/acknowledge:
    post:
      summary: Mark a notification as acknowledged
      description: |
        Records that the currently authenticated user has acknowledged
        the notification — typically used by team-wide notifications
        that need an explicit human sign-off (as opposed to merely
        being marked read). The acknowledging user is recorded on the
        `acknowledged_by` field of the notification.
      operationId: actionAcknowledgeNotification
      tags:
        - Notifications
      parameters:
        - $ref: '#/components/parameters/notificationId'
      responses:
        '204':
          description: The notification was successfully marked as acknowledged.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /notifications/{notificationId}/read:
    post:
      summary: Mark a notification as read
      description: |
        Marks the specified notification as read for the currently
        authenticated user. To mark several notifications in one
        request, use `actionBulkMarkNotificationsAsRead`.
      operationId: actionMarkNotificationAsRead
      tags:
        - Notifications
      parameters:
        - $ref: '#/components/parameters/notificationId'
      responses:
        '204':
          description: The notification was successfully marked as read.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /notifications/{notificationId}/unread:
    post:
      summary: Mark a notification as unread
      description: |
        Reverses a previous read or bulk-read action by clearing the
        `read_at` timestamp on the notification for the currently
        authenticated user.
      operationId: actionMarkNotificationAsUnread
      tags:
        - Notifications
      parameters:
        - $ref: '#/components/parameters/notificationId'
      responses:
        '204':
          description: The notification was successfully marked as unread.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /notifications/bulk-mark-as-read:
    post:
      summary: Bulk-mark notifications as read
      description: |
        Marks every notification whose ID is supplied as read for the
        currently authenticated user. IDs that don't correspond to a
        notification visible to the caller are silently skipped.
      operationId: actionBulkMarkNotificationsAsRead
      tags:
        - Notifications
      parameters:
        - $ref: '#/components/parameters/parameters_requiredSiteIdQuery'
      requestBody:
        description: The IDs of the notifications to mark as read.
        required: true
        content:
          application/json:
            schema:
              title: BulkMarkNotificationsAsRead
              type: object
              additionalProperties: false
              required:
                - notification_ids
              properties:
                notification_ids:
                  type: array
                  description: The IDs of the notifications to mark as read.
                  items:
                    type: string
                    format: uuid
      responses:
        '204':
          description: Notifications were successfully marked as read.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /personal-access-tokens:
    get:
      summary: Get the personal access tokens for the authenticated user
      description: |
        Returns metadata for every personal-access token issued to the
        currently authenticated user. The raw token values are never
        returned by this endpoint — use the token IDs together with
        `deletePersonalAccessToken` to revoke a token, or
        `createPersonalAccessToken` to issue a new one.
      operationId: listPersonalAccessTokens
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/ListPersonalAccessTokens'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create a personal access token for the authenticated user
      description: |
        Issues a new personal-access token for the currently
        authenticated user. The raw token value is included in the
        response; subsequent reads will only expose the metadata.
        Treat the response as sensitive.
      operationId: createPersonalAccessToken
      tags:
        - Users
      requestBody:
        description: The personal access token to create.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PersonalAccessToken'
      responses:
        '200':
          $ref: '#/components/responses/CreatePersonalAccessToken'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /personal-access-tokens/{tokenId}:
    delete:
      summary: Delete a personal access token for the authenticated user
      description: |
        Revokes a personal-access token issued to the currently
        authenticated user. The revocation takes effect immediately —
        any in-flight requests using the token will continue to
        succeed, but subsequent requests will be rejected.
      operationId: deletePersonalAccessToken
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/tokenId'
      responses:
        '204':
          description: The personal access token was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /sites/{siteId}/tax-info:
    parameters:
      - $ref: '#/components/parameters/siteId'
    get:
      summary: Get the tax details for a Site
      description: |
        Returns the registered tax identifier (e.g. VAT or GST number)
        and registered company address for a `Site`. These values appear
        on receipts, invoices, and exported tax reports.
      operationId: getSiteTaxInfo
      tags:
        - Sites
      responses:
        '200':
          $ref: '#/components/responses/SiteTaxInfo'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Update the tax details for a Site
      description: |
        Updates the registered tax identifier (e.g. VAT or GST number)
        and registered company address for a `Site`. The updated values
        take effect on invoices and tax reports generated after the
        request — historical receipts are unaffected.
      operationId: updateSiteTaxInfo
      tags:
        - Sites
      requestBody:
        $ref: '#/components/requestBodies/UpdateSiteTaxInfo'
      responses:
        '200':
          $ref: '#/components/responses/SiteTaxInfo'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /user-options:
    get:
      summary: Get all options for the current user
      description: |
        Returns the stored UI preferences for the currently authenticated
        user. Options are an opaque key/value map — see the `UserOptions`
        schema for details.
      operationId: getCurrentUserOptions
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/UserOptions'
        '400':
          description: The options could not be retrieved.
        '401':
          $ref: '#/components/responses/Unauthenticated'
    put:
      summary: Update options for the current user
      description: |
        Replaces or extends the stored UI preferences for the currently
        authenticated user. The request body is merged with any existing
        options at the top level — keys that are not present in the
        request are left untouched, but nested objects are replaced
        wholesale.
      operationId: updateCurrentUserOptions
      tags:
        - Users
      requestBody:
        description: An updated `UserOptions` object. Missing keys will not be updated.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserOptions'
      responses:
        '200':
          $ref: '#/components/responses/UserOptions'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /user/confirmed-two-factor-authentication:
    post:
      summary: Confirm 2FA enrolment for the authenticated user
      description: |
        Completes the two-factor-authentication enrolment flow by
        submitting the six-digit code from the user's authenticator app.
        Once confirmed, 2FA is active for subsequent logins.
      operationId: actionConfirmCurrentUserTwoFactorAuthentication
      tags:
        - Users
      requestBody:
        description: The 2FA code from the user's authenticator app.
        required: true
        content:
          application/json:
            schema:
              title: ConfirmCurrentUserTwoFactorAuthentication
              type: object
              additionalProperties: false
              required:
                - code
              properties:
                code:
                  type: string
                  description: The 2FA code from the user's authenticator app.
                  example: '123456'
      responses:
        '200':
          description: 2FA was successfully confirmed.
          content:
            application/json:
              schema:
                title: ConfirmCurrentUserTwoFactorAuthenticationResponse
                type: object
                nullable: true
                additionalProperties: true
                description: An empty JSON response.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /user/two-factor-authentication:
    post:
      summary: Enable 2FA for the authenticated user
      description: |
        Starts the two-factor-authentication enrolment flow for the
        currently authenticated user. The shared secret and QR code can
        be fetched via `getCurrentUserTwoFactorQrCode` /
        `getCurrentUserTwoFactorSecretKey`. The user must then confirm
        enrolment via `actionConfirmCurrentUserTwoFactorAuthentication`
        before 2FA is fully active.
      operationId: createCurrentUserTwoFactorAuthentication
      tags:
        - Users
      requestBody:
        content:
          application/json:
            schema:
              title: EnableCurrentUserTwoFactorAuthentication
              type: object
              additionalProperties: false
              description: An empty request body; reserved for future fields.
              properties: {}
      responses:
        '200':
          description: 2FA enrolment was successfully started.
          content:
            application/json:
              schema:
                title: EnableCurrentUserTwoFactorAuthenticationResponse
                type: object
                nullable: true
                additionalProperties: true
                description: An empty JSON response.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Disable 2FA for the authenticated user
      description: |
        Removes the registered second factor for the currently
        authenticated user. The user can re-enrol later via
        `createCurrentUserTwoFactorAuthentication`.
      operationId: deleteCurrentUserTwoFactorAuthentication
      tags:
        - Users
      requestBody:
        content:
          application/json:
            schema:
              title: DisableCurrentUserTwoFactorAuthentication
              type: object
              additionalProperties: false
              description: An empty request body; reserved for future fields.
              properties: {}
      responses:
        '200':
          description: 2FA was successfully disabled.
          content:
            application/json:
              schema:
                title: DisableCurrentUserTwoFactorAuthenticationResponse
                type: object
                nullable: true
                additionalProperties: true
                description: An empty JSON response.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /user/two-factor-qr-code:
    get:
      summary: Get the QR code for the authenticated user's 2FA enrolment
      description: |
        Returns a fresh QR code the user can scan with their
        authenticator app to register the shared secret. The QR code is
        returned both as an `otpauth://` URL and as an inline SVG ready
        for embedding in HTML.
      operationId: getCurrentUserTwoFactorQrCode
      tags:
        - Users
      responses:
        '200':
          description: The QR code was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TwoFactorQrCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /user/two-factor-recovery-codes:
    get:
      summary: Get the recovery codes for the authenticated user's 2FA
      description: |
        Returns the user's two-factor recovery codes — single-use codes
        the user can fall back to if they lose access to their
        authenticator app. Treat the response as sensitive; the codes
        should be displayed once and stored by the user offline.
      operationId: getCurrentUserTwoFactorRecoveryCodes
      tags:
        - Users
      responses:
        '200':
          description: The recovery codes were successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TwoFactorRecoveryCodes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /user/two-factor-secret-key:
    get:
      summary: Get the secret key for the authenticated user's 2FA enrolment
      description: |
        Returns the base32-encoded shared secret for the user's 2FA
        enrolment. Use this if the user is configuring their
        authenticator app by typing the secret in by hand rather than
        scanning the QR code returned by
        `getCurrentUserTwoFactorQrCode`.
      operationId: getCurrentUserTwoFactorSecretKey
      tags:
        - Users
      responses:
        '200':
          description: The secret key was successfully retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TwoFactorSecretKey'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /users/{userId}/password-reset:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    post:
      summary: Reset a user's password
      description: |
        Triggers a password-reset flow for the target user. The user
        receives an email containing a one-time link they can use to
        choose a new password. This endpoint does not return the new
        password and does not invalidate existing sessions until the
        reset link is followed.
      operationId: actionResetUserPassword
      tags:
        - Users
      responses:
        '200':
          description: The password reset was successfully triggered.
          content:
            application/json:
              schema:
                title: ResetUserPasswordResponse
                type: object
                additionalProperties: false
                required:
                  - message
                properties:
                  message:
                    type: string
                    description: A description for the response.
                    example: Success!
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /users/{userId}/two-factor-authentication:
    parameters:
      - $ref: '#/components/parameters/parameters_userId-2'
    delete:
      summary: Disable 2FA for a user
      description: |
        Administratively disables two-factor authentication for the
        target user, removing any registered authenticator and recovery
        codes. Use this when a user has lost access to their second
        factor and the caller has verified the user's identity through
        another channel.
      operationId: deleteUserTwoFactorAuthentication
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/parameters_siteIdQuery-2'
      responses:
        '204':
          description: 2FA was successfully disabled for the user.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointment-types/{appointmentTypeId}/check-rules:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeId'
    get:
      summary: Check price rule coverage for an appointment type
      description: |
        Validates that every active availability rule on the
        `AppointmentType` is also covered by a matching `PriceRule`. The
        response reports any date ranges where the appointment type is
        available but doesn't have a configured price — useful as a
        pre-publish sanity check when seeding a new appointment type and
        when shifting availability windows.
      operationId: getAppointmentTypeCheckRules
      tags:
        - AppointmentTypes
      responses:
        '200':
          description: The check was successfully performed.
          content:
            application/json:
              schema:
                title: GetAppointmentTypeCheckRulesResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    title: PriceAvailabilityRuleCheck
                    type: object
                    additionalProperties: false
                    required:
                      - valid
                      - missing_dates
                    properties:
                      valid:
                        type: boolean
                        description: |
                          Whether every availability rule on the
                          appointment type has matching price coverage.
                      missing_dates:
                        type: array
                        description: |
                          Date ranges where the appointment type is
                          available but no price rule is configured.
                        items:
                          title: PriceAvailabilityRuleGap
                          type: object
                          additionalProperties: false
                          required:
                            - from
                            - to
                          properties:
                            from:
                              type: string
                              format: date
                              description: The first date the gap covers.
                              example: '2026-10-01'
                            to:
                              type: string
                              format: date
                              description: The last date the gap covers.
                              example: '2026-11-01'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/appointments/{appointmentId}/check:
    parameters:
      - $ref: '#/components/parameters/appointmentId'
    put:
      summary: Check whether an Appointment update would be allowed
      description: |
        Dry-runs an `Appointment` update without persisting the change.
        Reports whether the proposed assignment of practitioners, room
        and time-of-day slot would succeed.

        Note: this endpoint validates against time-of-day only — it
        is NOT a full reschedule dry-run. The body is a strict subset
        of `UpdateAppointment` (`practitioner_ids`, `room_id` and a
        `HH:mm` `start_time`); other writable appointment fields (move,
        stage, item_configuration, etc.) are not consulted here. Use
        `PUT /shop/appointments/{appointmentId}` to actually persist
        a reschedule.

        Use this to surface conflicts (overlapping bookings, room
        capacity, equipment availability, opening hours) to the operator
        before they commit a drag-and-drop move on the calendar. The
        response indicates whether the update is allowed, lists the
        specific availability errors that would block it, and reports
        whether the current user has the `reservations.override-rules`
        permission to bypass them.
      operationId: updateAppointmentCheck
      tags:
        - Appointments
      requestBody:
        description: The proposed slot assignment to test.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckAppointmentBody'
      responses:
        '200':
          description: The check was successfully carried out.
          content:
            application/json:
              schema:
                title: UpdateAppointmentCheckResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    title: UpdateAppointmentCheckResult
                    type: object
                    additionalProperties: false
                    required:
                      - allowed
                      - errors
                      - user_can_override
                    properties:
                      allowed:
                        type: boolean
                        description: Whether the proposed update would be allowed.
                      errors:
                        type: array
                        description: |
                          If the update would not be allowed, the specific
                          reasons why. Each entry has a `type` discriminator
                          and a human-readable `message`.
                        items:
                          title: UpdateAppointmentCheckError
                          type: object
                          additionalProperties: false
                          required:
                            - type
                            - message
                          properties:
                            type:
                              type: string
                              description: |
                                Identifier for the kind of error encountered.
                              example: NoSlotException
                            message:
                              type: string
                              description: |
                                A message describing the specific reason
                                the update would be blocked.
                              example: The requested time slot isn't valid for this appointment type.
                      user_can_override:
                        type: boolean
                        description: |
                          Whether the current user holds the
                          `reservations.override-rules` permission and can
                          perform the update regardless of `allowed`.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/basket/{basketId}/offered-retail-products:
    parameters:
      - $ref: '#/components/parameters/basketId'
    get:
      summary: List cross-sell retail products for a basket
      description: |
        Returns a curated list of retail `Product`s to offer to the
        customer during checkout. Selection is driven by the current
        basket contents: a product appears here if it is configured as a
        cross-sell on any of the basket's existing line items.

        The intended consumer is the storefront's "you may also like"
        panel on the checkout screen. The list is unpaginated and
        site-scoped to the basket's site.
      operationId: listBasketOfferedRetailProducts
      tags:
        - Baskets
      responses:
        '200':
          description: The cross-sell products were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListBasketOfferedRetailProducts
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/schemas_Product'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/email-lists:
    post:
      summary: Create an email list from shop criteria
      description: |
        Builds an auto-populated email list in the Customer API from
        criteria evaluated against the Shop API. The intended use case is
        one-shot mailshots: select an order filter or session attendance
        in the operator UI and have the matching customers piped into a
        Mailchimp-compatible list without manual export.

        The criteria type determines which selector fields are required —
        `order_filters` expects the `filters` object, `session_attendees`
        expects `session_id`, and so on.
      operationId: createEmailList
      tags:
        - Marketing
      requestBody:
        description: The criteria the list should be populated from.
        required: true
        content:
          application/json:
            schema:
              title: CreateEmailList
              type: object
              additionalProperties: false
              required:
                - name
                - criteria_type
              properties:
                name:
                  type: string
                  description: The display name of the email list.
                  example: January orders
                criteria_type:
                  type: string
                  description: |
                    Which selector the list is populated from. Determines
                    which of the optional fields below must be supplied.
                  enum:
                    - order_filters
                    - session_attendees
                  example: order_filters
                filters:
                  type: object
                  additionalProperties: true
                  description: |
                    For `criteria_type: order_filters`, the order filters
                    applied — same shape as the order-list query parameters.
                session_id:
                  type: string
                  description: |
                    For `criteria_type: session_attendees`, the session
                    whose attendees should be added to the list.
                  example: 5dcb47800000000000000000
                site_id:
                  type: string
                  description: The site the email list belongs to.
                  example: 00000000-0000-0000-0000-111111111111
      responses:
        '200':
          description: The email list was successfully created.
          content:
            application/json:
              schema:
                title: CreateEmailListResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    title: CreatedEmailList
                    type: object
                    additionalProperties: false
                    required:
                      - id
                      - name
                    properties:
                      id:
                        type: string
                        description: The ID of the created email list.
                        example: 00000000-0000-0000-0000-111111111111
                      name:
                        type: string
                        description: The display name of the created email list.
                        example: January orders
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/internal/orders/{orderId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-4'
  /shop/internal/orders/{orderId}/guests/{guestId}:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-4'
      - $ref: '#/components/parameters/parameters_guestId-2'
  /shop/item-availability/appointment-dates/{appointmentTypeId}:
    parameters:
      - $ref: '#/components/parameters/appointmentTypeIdPath'
  /shop/item-availability/package-slots/{siteId}/{packageId}:
    parameters:
      - $ref: '#/components/parameters/parameters_siteIdPath'
      - $ref: '#/components/parameters/packageIdPath'
  /shop/memberships:
    post:
      summary: Create a membership order
      description: |
        Creates a new basket for the membership purchase and produces the
        `Membership` against the given customer. Use this when the
        storefront has already collected the membership type, rate and
        target customer and you want to skip straight to a payment-ready
        basket.

        The returned `Membership` will be in `reserved` state — call the
        customer-side `confirmMembership` endpoint once the basket is
        paid to activate it.
      operationId: createMembershipOrder
      tags:
        - Baskets
      requestBody:
        description: The membership purchase to create.
        required: true
        content:
          application/json:
            schema:
              title: CreateMembershipOrder
              type: object
              additionalProperties: false
              required:
                - customer_id
                - site_id
                - membership_type_id
                - membership_rate_id
              properties:
                customer_id:
                  type: string
                  format: uuid
                  description: The customer the membership is being purchased for.
                  example: 00000000-0000-0000-0000-444444444444
                site_id:
                  type: string
                  format: uuid
                  description: The site the membership belongs to.
                  example: 00000000-0000-0000-0000-111111111111
                membership_type_id:
                  type: string
                  format: uuid
                  description: The `MembershipType` being purchased.
                  example: 00000000-0000-0000-0000-222222222222
                membership_rate_id:
                  type: string
                  format: uuid
                  description: The chosen `MembershipRate` within the type.
                  example: 00000000-0000-0000-0000-333333333333
                start_date:
                  type: string
                  format: date
                  description: |
                    The date the membership should start, as `YYYY-MM-DD`.
                    Defaults to today when omitted.
                  example: '2026-07-28'
                end_date:
                  type: string
                  format: date
                  nullable: true
                  description: |
                    The date the membership should end, as `YYYY-MM-DD`.
                    Omit (or pass `null`) for evergreen memberships that
                    run until cancelled.
                  example: '2027-07-28'
                payment_method_id:
                  type: string
                  nullable: true
                  example: 5e1e3f6c-2a44-4f6e-8c61-9c1f7d2e1c11
                  description: |
                    Optional ID of a payment method already on file for the
                    customer. When provided it must reference a payment
                    method belonging to `customer_id`; pass `null` (or omit)
                    to skip attaching one at order-creation time.
                source:
                  type: string
                  enum:
                    - self_signup
                    - app
                    - import
                  description: |
                    Where the membership purchase originated. `self_signup`
                    indicates the public self-signup flow, `app` indicates
                    the back-office app, and `import` is reserved for bulk
                    imports.
                external_ref:
                  type: string
                  nullable: true
                  example: PMS-2026-08-12345
                  description: |
                    Optional external reference for the membership purchase
                    (e.g. an ID from a PMS or partner system).
      responses:
        '201':
          description: The membership order was successfully created.
          content:
            application/json:
              schema:
                title: CreateMembershipOrderResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Membership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/my-account/orders:
    get:
      summary: List orders for the authenticated customer
      description: |
        Returns the authenticated customer's order history — completed
        baskets along with item details. Intended for the "My Bookings"
        screens of customer-facing apps and the storefront.

        Requires customer authentication; staff API tokens cannot use
        this endpoint (use `GET /shop/orders` instead).
      operationId: listMyAccountOrders
      tags:
        - MyAccount
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListOrders'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/order-intake-forms/{orderIntakeFormId}/guests:
    parameters:
      - $ref: '#/components/parameters/orderIntakeFormId'
    get:
      summary: List guests requiring an intake form for an order
      description: |
        Returns the guests on an order who still need to complete an
        intake form, with their display name and customer ID. Used by
        customer-facing UIs to prompt the right person to fill out the
        next outstanding form before their visit.
      operationId: listOrderIntakeFormGuests
      tags:
        - IntakeForms
      responses:
        '200':
          description: |
            The guests requiring intake forms were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListOrderIntakeFormGuests
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      title: OrderIntakeFormGuest
                      type: object
                      additionalProperties: false
                      required:
                        - id
                        - name
                      properties:
                        id:
                          type: string
                          description: The ID of the guest.
                          example: 634d6e9f413841226003acc4
                        name:
                          type: string
                          description: The display name of the guest.
                          example: John Doe
                        customer_id:
                          type: string
                          nullable: true
                          description: |
                            The ID of the customer linked to this guest, if any.
                          example: 634d6e9f413841226003acc3
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/orders/{orderId}/items/{itemId}/delivery_date:
    parameters:
      - $ref: '#/components/parameters/parameters_orderId-2'
      - $ref: '#/components/parameters/parameters_itemId'
    put:
      summary: Update the delivery date of a voucher purchase order item
      description: |
        Sets the planned delivery date on a voucher-purchase line item.
        Only meaningful for line items whose underlying offering is a
        voucher purchase with `delivery_method_type: physical` — i.e.
        physical voucher dispatches that need scheduling.

        The path uses `delivery_date` (underscore) for historical reasons
        and is preserved here to keep parity with the legacy Trybe API
        URL contract.
      tags:
        - Orders
      operationId: updateOrderItemDeliveryDate
      requestBody:
        description: The new delivery date to assign.
        required: true
        content:
          application/json:
            schema:
              title: UpdateOrderItemDeliveryDate
              type: object
              additionalProperties: false
              required:
                - delivery_date
              properties:
                delivery_date:
                  type: string
                  format: date
                  description: |
                    The new dispatch date for the voucher, as an ISO 8601
                    date (no time component). The site's mail-out workflow
                    will schedule the print/post job for this date.
                  example: '2026-12-20'
      responses:
        '200':
          $ref: '#/components/responses/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/organisations/{organisationId}/category/{categoryId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_categoryId-5'
    post:
      summary: Copy a Category (singular alias)
      tags:
        - Organisations
      operationId: copyOrganisationCategoryLegacy
      description: |
        Legacy URL alias for `POST
        /shop/organisations/{organisationId}/categories/{categoryId}/copy`.
        Routes to the same handler — copies the category and overlays any
        properties supplied in the request body.

        New integrations should use the plural route; this endpoint
        remains for backwards compatibility with API consumers that were
        built against the original singular URL.
      requestBody:
        description: Pass any category properties that should be overridden on the copied resource.
        required: false
        content:
          application/json:
            schema:
              title: CopyOrganisationCategoryLegacy
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  description: |
                    Display name to give the duplicated category. 1-120
                    characters; must not contain HTML.
                  example: Massages (Summer 2026)
                voucher_applicable:
                  type: boolean
                  description: |
                    Whether the new category can be selected when issuing
                    vouchers.
      responses:
        '201':
          $ref: '#/components/responses/ShowCategory'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/organisations/{organisationId}/label/{labelId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_organisationId-2'
      - $ref: '#/components/parameters/parameters_labelId'
    post:
      summary: Duplicate a Label (singular alias)
      description: |
        Legacy URL alias for `POST
        /shop/organisations/{organisationId}/labels/{labelId}/copy`. Routes
        to the same handler — duplicates the label with new fields
        overlaid from the body.

        New integrations should use the plural route; this endpoint
        remains for backwards compatibility with API consumers that were
        built against the original singular URL.
      operationId: copyOrganisationLabelLegacy
      tags:
        - Organisations
      requestBody:
        description: Properties to set on the copied label.
        required: true
        content:
          application/json:
            schema:
              title: CopyOrganisationLabelLegacy
              type: object
              additionalProperties: false
              required:
                - name
                - site_ids
              properties:
                name:
                  type: string
                  description: |
                    Display name for the new copy. Plain text only;
                    maximum 40 characters.
                  maxLength: 40
                  example: VIP Guests (West Sites)
                color:
                  type: string
                  nullable: true
                  description: |
                    Six-digit hex colour with a leading `#`. Defaults to
                    the source's colour when omitted.
                  pattern: ^#[0-9a-fA-F]{6}$
                  example: '#3366cc'
                site_ids:
                  type: array
                  description: |
                    UUIDs of the sites the copy is visible at. Every ID
                    must belong to the organisation in the path.
                  items:
                    type: string
                    format: uuid
                    example: 00000000-0000-0000-0000-111111111111
      responses:
        '200':
          $ref: '#/components/responses/ShowOrganisationLabel'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/item-choices/{itemChoiceId}/options:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/itemChoiceId'
    get:
      summary: List options for a package item choice
      tags:
        - Packages
      operationId: listPackageItemChoiceOptions
      description: |
        Returns every `PackageItemChoiceOption` configured on the named
        `PackageItemChoice`. Each option names a specific offering (e.g.
        a particular appointment type or retail product) that the parent
        choice may be filled by, plus the price uplift the option carries.
      responses:
        '200':
          $ref: '#/components/responses/ListPackageItemChoiceOptions'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add an option to a package item choice
      tags:
        - Packages
      operationId: createPackageItemChoiceOption
      description: |
        Adds a new `PackageItemChoiceOption` to the parent
        `PackageItemChoice`. The body sets the offering the option points
        at and any price uplift; the option is appended to the choice's
        existing list.

        Requires the `SETTINGS_MANAGE` permission on the package's site.
      requestBody:
        description: The option to add to the choice.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PackageItemChoiceOption'
      responses:
        '201':
          $ref: '#/components/responses/ShowPackageItemChoiceOption'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/packages/{packageId}/item-choices/{itemChoiceId}/options/{optionId}:
    parameters:
      - $ref: '#/components/parameters/packageId'
      - $ref: '#/components/parameters/itemChoiceId'
      - $ref: '#/components/parameters/parameters_optionId'
    get:
      summary: Get a package item choice option
      tags:
        - Packages
      operationId: getPackageItemChoiceOption
      description: |
        Returns a single `PackageItemChoiceOption` on the named
        `PackageItemChoice`.
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageItemChoiceOption'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a package item choice option
      tags:
        - Packages
      operationId: updatePackageItemChoiceOption
      description: |
        Updates the offering or price uplift on an existing
        `PackageItemChoiceOption`. Fields omitted from the body are left
        unchanged.

        Requires the `SETTINGS_MANAGE` permission on the package's site.
      requestBody:
        description: The fields to update on the option.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PackageItemChoiceOption'
      responses:
        '200':
          $ref: '#/components/responses/ShowPackageItemChoiceOption'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a package item choice option
      tags:
        - Packages
      operationId: deletePackageItemChoiceOption
      description: |
        Removes a `PackageItemChoiceOption` from its parent
        `PackageItemChoice`. Existing bookings of the package are
        unaffected; the option is just hidden from the choice's available
        options going forward. Requires the `SETTINGS_MANAGE` permission
        on the package's site.
      responses:
        '204':
          description: The option was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/products/barcode-search/{code}:
    parameters:
      - $ref: '#/components/parameters/parameters_code-7'
    get:
      summary: Look up a product by barcode
      tags:
        - Products
      operationId: getProductByBarcode
      description: |
        Looks up a single retail product by its barcode. Returns `404` if
        no product with the supplied barcode is visible to the caller's
        site scope. For barcode-driven product search with site scoping
        consider `GET /shop/barcode-search/products/{code}` instead.
      responses:
        '200':
          $ref: '#/components/responses/ProductResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/reports/deposit-ledger:
    get:
      summary: Get the deposit ledger report
      description: |
        Returns the deposit-ledger report — a tabular summary of voucher
        and credit deposit positions across the site/date range. The
        response is shaped for display rather than programmatic
        consumption; consider `GET /shop/reports/deposit-ledger-v2/list`
        for a structured per-payable breakdown.

        Pass `Accept: text/csv` to receive the same report as a CSV
        download instead of a JSON `TableReport`.
      tags:
        - Reports
      operationId: getDepositLedgerReport
      parameters:
        - $ref: '#/components/parameters/dateFrom'
        - $ref: '#/components/parameters/dateTo'
        - $ref: '#/components/parameters/siteIdOptional'
      responses:
        '200':
          description: The deposit ledger report was successfully retrieved.
          content:
            application/json:
              schema:
                title: GetDepositLedgerReportResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/TableReport'
            text/csv:
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/deposit-ledger/queue:
    get:
      summary: Queue the deposit ledger report (v1)
      description: |
        Queues an asynchronous build of the v1 deposit-ledger report.
        Returns a `QueuedJob` whose `output` will contain a download URL
        once processing finishes. Exposed at the legacy v1 URL alongside
        the v2 counterpart at `/shop/reports/deposit-ledger-v2/queue` for
        callers that have not yet migrated.
      tags:
        - Reports
      parameters:
        - $ref: '#/components/parameters/dateFrom'
        - $ref: '#/components/parameters/dateTo'
        - $ref: '#/components/parameters/siteIdOptional'
      operationId: queueDepositLedgerReport
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/reports/trybe-payments-balance/queue:
    get:
      summary: Queue the Trybe Payments balance report
      description: |
        Queues an asynchronous build of the Trybe Payments balance report
        for the given site and date range. Returns a `QueuedJob` whose
        `output` will carry a download URL once the job completes. Use
        this for larger date ranges that the synchronous endpoint
        (`GET /shop/reports/trybe-payments-balance`) would time out on.
      tags:
        - Reports
      operationId: queueTrybePaymentsBalanceReport
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-71'
        - $ref: '#/components/parameters/dateFromQuery'
        - $ref: '#/components/parameters/dateToQuery'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
  /shop/session-bookings/{bookingId}/check-in:
    parameters:
      - $ref: '#/components/parameters/bookingId'
    post:
      summary: Check a guest in to a session booking
      description: |
        Marks a `SessionBooking` as checked in. Used by front-of-house
        staff and self-service kiosks at the start of a session to record
        arrival. Setting `is_checked_in` to `false` reverses an earlier
        check-in.

        The request body is optional — calling the endpoint with no body
        is equivalent to passing `{ "is_checked_in": true }`.
      operationId: actionCheckInSessionBooking
      tags:
        - SessionBookings
      requestBody:
        description: 'Pass `is_checked_in: false` to undo a previous check-in.'
        required: false
        content:
          application/json:
            schema:
              title: CheckInSessionBookingRequest
              type: object
              additionalProperties: false
              properties:
                is_checked_in:
                  type: boolean
                  description: |
                    Set to `false` to clear an existing check-in. Defaults
                    to `true` when omitted, marking the booking as
                    checked in.
                  example: true
      responses:
        '200':
          $ref: '#/components/responses/ShowSessionBooking'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-bookings/{bookingId}/check-out:
    parameters:
      - $ref: '#/components/parameters/bookingId'
    post:
      summary: Check a guest out of a session booking
      description: |
        Marks a `SessionBooking` as checked out. Used by front-of-house
        staff and self-service kiosks at the end of a session to record
        departure. Setting `is_checked_out` to `false` reverses an earlier
        check-out.

        The request body is optional — calling the endpoint with no body
        is equivalent to passing `{ "is_checked_out": true }`.
      operationId: actionCheckOutSessionBooking
      tags:
        - SessionBookings
      requestBody:
        description: 'Pass `is_checked_out: false` to undo a previous check-out.'
        required: false
        content:
          application/json:
            schema:
              title: CheckOutSessionBookingRequest
              type: object
              additionalProperties: false
              properties:
                is_checked_out:
                  type: boolean
                  description: |
                    Set to `false` to clear an existing check-out. Defaults
                    to `true` when omitted, marking the booking as
                    checked out.
                  example: true
      responses:
        '200':
          $ref: '#/components/responses/ShowSessionBooking'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/session-bookings/{bookingId}/no-show:
    parameters:
      - $ref: '#/components/parameters/bookingId'
    post:
      summary: Mark a session booking as a no-show
      description: |
        Flags a `SessionBooking` as a no-show. Used by front-of-house
        staff after the session start time has elapsed without the guest
        arriving. Setting `is_no_show` to `false` reverses an earlier
        no-show flag.

        The request body is optional — calling the endpoint with no body
        is equivalent to passing `{ "is_no_show": true }`.
      operationId: actionMarkSessionBookingNoShow
      tags:
        - SessionBookings
      requestBody:
        description: 'Pass `is_no_show: false` to undo a previous no-show flag.'
        required: false
        content:
          application/json:
            schema:
              title: NoShowSessionBookingRequest
              type: object
              additionalProperties: false
              properties:
                is_no_show:
                  type: boolean
                  description: |
                    Set to `false` to clear an existing no-show flag.
                    Defaults to `true` when omitted.
                  example: true
      responses:
        '200':
          $ref: '#/components/responses/ShowSessionBooking'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/sites:
    get:
      summary: List shop sites
      description: |
        Returns every `Site` the caller has permission to see, projected
        through the shop API's `ShopSite` shape. The projection includes
        storefront-facing configuration (currency, payment types, email
        branding, feature flags, category mappings) that is not exposed
        on the bare `Site` record.

        The list is unpaginated — sites per organisation are expected to
        be small enough to return in a single response.
      operationId: listShopSites
      tags:
        - Sites
      responses:
        '200':
          description: The sites were successfully retrieved.
          content:
            application/json:
              schema:
                title: ListShopSites
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ShopSite'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/visit-intake-forms:
    get:
      summary: List completed visit intake forms
      tags:
        - IntakeForms
      operationId: listVisitIntakeForms
      description: |
        Returns a paginated list of completed `VisitIntakeForm`s, filtered
        by the supplied site, customer, basket or type. Use this to
        surface a guest's prior intake responses in customer-service
        flows and on the visit log.
      parameters:
        - $ref: '#/components/parameters/parameters_siteIdQuery-3'
        - $ref: '#/components/parameters/parameters_customerIdQuery'
        - $ref: '#/components/parameters/basketIdQuery'
        - $ref: '#/components/parameters/parameters_typeQuery'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListVisitIntakeForms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /shop/visit-intake-forms-for-orders:
    post:
      summary: Get visit intake forms for an order
      tags:
        - IntakeForms
      operationId: getVisitIntakeFormsForOrders
      description: |
        Returns the IDs of the `VisitIntakeForm`s associated with an
        order. Although the operation is read-only the request uses
        `POST` so a complex order/basket selector can be supplied without
        fitting it into a URL query string.
      parameters:
        - $ref: '#/components/parameters/parameters_basketId'
        - $ref: '#/components/parameters/parameters_siteId-75'
      responses:
        '200':
          $ref: '#/components/responses/ListVisitIntakeForms'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/visit-intake-forms-for-orders/pdf:
    post:
      summary: Build a PDF of visit intake forms for an order
      tags:
        - IntakeForms
      operationId: getVisitIntakeFormsForOrdersPdf
      description: |
        Queues the construction of a combined PDF containing every
        completed `VisitIntakeForm` attached to the order. The response
        carries a temporary `url` from which the rendered PDF can be
        downloaded once the build completes.
      parameters:
        - $ref: '#/components/parameters/parameters_basketId'
        - $ref: '#/components/parameters/parameters_siteId-75'
      responses:
        '200':
          description: The PDF download URL was successfully generated.
          content:
            application/json:
              schema:
                title: GetVisitIntakeFormsForOrdersPdfResponse
                type: object
                additionalProperties: false
                required:
                  - url
                properties:
                  url:
                    type: string
                    description: |
                      Temporary URL from which the rendered PDF can be
                      downloaded. The URL is signed and time-limited.
                    example: https://files.trybe.app/visit-intake/...
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/visit-intake-forms/{visitIntakeFormId}:
    parameters:
      - $ref: '#/components/parameters/visitIntakeFormId'
    get:
      summary: Get a completed visit intake form
      tags:
        - IntakeForms
      operationId: getVisitIntakeForm
      description: |
        Returns the captured-data record of a single completed
        `VisitIntakeForm` by ID.
      responses:
        '200':
          $ref: '#/components/responses/ShowVisitIntakeForm'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/visit-intake-forms/{visitIntakeFormId}/html:
    parameters:
      - $ref: '#/components/parameters/visitIntakeFormId'
    get:
      summary: Get the rendered HTML of a visit intake form
      tags:
        - IntakeForms
      operationId: getVisitIntakeFormHtml
      description: |
        Returns the rendered HTML representation of a completed
        `VisitIntakeForm` — suitable for embedding in admin UIs or
        converting to PDF. The questions and the guest's answers are
        laid out in a print-ready format.
      responses:
        '200':
          description: The intake form HTML was successfully retrieved.
          content:
            text/html:
              schema:
                type: string
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/voucher-codes/{voucherCodeId}/revoke:
    parameters:
      - $ref: '#/components/parameters/voucherCodeId'
    post:
      summary: Revoke a VoucherCode
      description: |
        Revokes a `VoucherCode`, moving it to status `revoked` and
        preventing any further redemptions. Existing redemptions remain
        on the code's history. Used by customer-service teams when a
        voucher needs to be cancelled (for example after a chargeback on
        the purchasing order, or in response to a fraud report).

        Revoking a code is permanent — there is no `unrevoke`. To restore
        spending power to a customer after a mistaken revoke, issue a
        fresh voucher.
      operationId: actionRevokeVoucherCode
      tags:
        - VoucherCodes
      responses:
        '200':
          description: The voucher code was successfully revoked.
          content:
            application/json:
              schema:
                title: RevokeVoucherCodeResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VoucherCode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/voucher-lookup/{voucherCode}:
    parameters:
      - $ref: '#/components/parameters/parameters_voucherCode'
      - $ref: '#/components/parameters/requiredSiteId'
    get:
      summary: Look up voucher details by code
      description: |
        Public endpoint for resolving a voucher code into the runtime
        `VoucherCodeLookup` shape — its remaining balance, validity
        window, owning voucher type or external voucher, and the list of
        offerings the code may be redeemed against. Used by the customer-
        facing storefront to validate a code at checkout before the basket
        is committed.

        Supports both Trybe-native `VoucherCode`s and integration-issued
        external vouchers (e.g. GiftPro) — see the `payment_processor`
        discriminator on the response.
      operationId: getVoucherLookup
      tags:
        - Vouchers
      responses:
        '200':
          description: The voucher details were successfully retrieved.
          content:
            application/json:
              schema:
                title: GetVoucherLookupResponse
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VoucherCodeLookup'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/voucher-purchases/{voucherPurchaseId}/preview-email:
    parameters:
      - $ref: '#/components/parameters/voucherPurchaseId'
    post:
      summary: Preview a voucher recipient email
      description: |
        Renders the gift email that would be sent to a voucher recipient
        without dispatching it. Use this in operator UIs to show staff
        exactly what the recipient will see — including the rendered HTML
        body, sender, subject and CC/BCC list — before they commit to
        sending.

        Pass recipient overrides in the body to preview against a
        different address (for example, a staff test inbox).
      operationId: actionPreviewVoucherPurchaseEmail
      tags:
        - VoucherPurchases
      requestBody:
        description: Optional recipient overrides for the preview.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendVoucherPurchaseEmail'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherPurchaseMailable'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/voucher-purchases/{voucherPurchaseId}/send-email:
    parameters:
      - $ref: '#/components/parameters/voucherPurchaseId'
    post:
      summary: Send a voucher recipient email
      description: |
        Sends the gift email to the recipient on file for a voucher
        purchase. The rendered email is also returned in the response so
        operator UIs can preview what was sent.

        Pass recipient overrides in the body to redirect the send — most
        commonly when the original delivery bounced or the customer
        supplied a corrected email address.
      operationId: actionSendVoucherPurchaseEmail
      tags:
        - VoucherPurchases
      requestBody:
        description: |
          Recipient overrides for this send. Pass an empty object to use
          the recipient details stored on the voucher purchase.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendVoucherPurchaseEmail'
      responses:
        '200':
          $ref: '#/components/responses/ShowVoucherPurchaseMailable'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/yield-insights:
    get:
      summary: Get yield insights
      tags:
        - YieldInsights
      operationId: getYieldInsights
      description: |
        Returns a site-level summary of how yield pricing is set up and
        performing over a recent reporting period: the opportunity for
        demand-based pricing (utilisation, peak and quiet spells) and what
        yield rules have earned since they were switched on.

        The four state flags (`has_occupancy_data`, `is_yield_enabled`,
        `opportunities.has_data`, `performance.has_data`) are always
        present, so a dashboard can decide which panels to render before
        reading any stats. The stat fields themselves are `null` until the
        underlying calculation has data to work from.

        Monetary amounts are integers in the minor units of the top-level
        `currency` — format them client-side.

        For a per-sale breakdown of every price a yield rule moved, use the
        [yielded sales report](/endpoints/Reports#listYieldedSales).
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-76'
        - $ref: '#/components/parameters/yieldInsightsPeriod'
      responses:
        '200':
          $ref: '#/components/responses/GetYieldInsights'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/yield-insights/heatmap:
    get:
      summary: Get the yield insights demand heatmap
      tags:
        - YieldInsights
      operationId: getYieldInsightsHeatmap
      description: |
        Returns how full a site's bookable capacity was by weekday and hour over a
        recent reporting period, so an operator can see when demand is heavy enough
        to price against.

        Each average is the share of bookable minutes that were booked in that
        weekday and hour across the period — booked time over usable capacity, with
        time blocked out by staff reducing capacity rather than counting as demand.
        An average is `null` rather than `0` where nothing was bookable, so a closed
        hour reads differently from an empty one.

        `type` selects which offerings the averages cover.

        `has_occupancy_data` is always present, so a dashboard can decide whether to
        render the grid before reading it. `heatmap` is empty until the underlying
        calculation has data to work from.

        Separate from the [yield insights summary](/endpoints/YieldInsights#getYieldInsights)
        because `type` scopes only the grid: a dashboard switching between offering
        types re-reads this without re-reading the summary.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-76'
        - $ref: '#/components/parameters/yieldInsightsPeriod'
        - $ref: '#/components/parameters/yieldInsightsHeatmapType'
      responses:
        '200':
          $ref: '#/components/responses/GetYieldInsightsHeatmap'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/yield-insights/revenue-comparison:
    get:
      summary: Get the yield insights revenue comparison
      tags:
        - YieldInsights
      operationId: getYieldInsightsRevenueComparison
      description: |
        Returns what the site took over the reporting period against what the same
        bookings would have made at baseline prices, as the two lines of a chart
        plus the overall uplift between them.

        `has_data` needs both occupancy history and yield rules — with no rules
        there is nothing to compare against. `series` is empty until the underlying
        calculation has data to work from.

        Separate from the [yield insights summary](/endpoints/YieldInsights#getYieldInsights)
        because it returns a series rather than a stat. For the single
        since-inception figure, read `performance.additional_revenue` there instead.

        Amounts are integers in the minor units of the top-level `currency`. Sites
        without the `advanced_yield_management` feature respond `404`.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-76'
        - $ref: '#/components/parameters/yieldInsightsPeriod'
      responses:
        '200':
          $ref: '#/components/responses/GetYieldInsightsRevenueComparison'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/yield-insights/room-occupancy:
    get:
      summary: Get yield insights room and area occupancy
      tags:
        - YieldInsights
      operationId: getYieldInsightsRoomOccupancy
      description: |
        Returns how full each of a site's bookable resources was by hour over a
        recent reporting period, so an operator can see which rooms carry the demand
        and which sit empty.

        Each average is the share of that resource's bookable minutes which were
        booked in that hour across the period, with time blocked out by staff
        reducing capacity rather than counting as demand. An average is `null`
        rather than `0` where nothing was bookable, so a closed hour reads
        differently from an empty one.

        Rows cover treatment rooms today; `kind` distinguishes them from bookable
        areas, which are added as further rows once their capacity is measured.

        `avgs` is empty until the underlying calculation has data to work from,
        while the rows themselves are always returned, so a grid can render its
        axes before any fill rate exists.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-76'
        - $ref: '#/components/parameters/yieldInsightsPeriod'
      responses:
        '200':
          $ref: '#/components/responses/GetYieldInsightsRoomOccupancy'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/yield-rules:
    get:
      summary: List YieldRules
      tags:
        - YieldRules
      operationId: listYieldRules
      description: |
        Lists the `YieldRules` configured for a site.

        Pass `offering_type` and `offering_id` together to narrow the list to the
        rules affecting one offering, or `created_batch_id` to return only the rules
        created by a single request.

        Requires the `advanced_yield_management` feature. Sites without it return
        `404`, since yield rules do not exist as a concept for them.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId-77'
        - $ref: '#/components/parameters/parameters_offeringType-9'
        - $ref: '#/components/parameters/parameters_offeringId-9'
        - $ref: '#/components/parameters/createdBatchId'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListYieldRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    post:
      summary: Create YieldRules
      tags:
        - YieldRules
      operationId: createYieldRules
      description: |
        Creates a `YieldRule` for each offering supplied.

        Rules are per-offering. Applying one definition to several offerings is a
        convenience at creation only: it produces an independent rule for each, so
        editing or deleting one afterwards leaves the rest untouched, and offerings
        created later do not pick the rule up.

        Every offering must belong to the site and have a standard price for the
        adjustment to work from, and they must all be the same `offering_type`: what a
        rule may contain differs between types, since an appointment has a
        practitioner to measure utilisation against and an area booking type does not.
        If any offering is rejected, no rules are created.

        Selections of more than 200 offerings are written by a background job and
        answered with `202` and the `created_batch_id` the rules will carry, rather
        than holding the response open for several seconds. Poll the list endpoint
        with that id to follow them appearing.

        A rule that lowers a price needs the offering to say when reductions may
        start. Send `reduction_advance_interval` to set that window on every offering
        the rule is created for, or leave it out where they are already configured.
        Creating a rule is the only time it can be set through this resource; changing
        it afterwards is done from the offering.

        Requires the `advanced_yield_management` feature and the same permission as
        editing an offering's price rules.
      requestBody:
        $ref: '#/components/requestBodies/CreateYieldRules'
      responses:
        '201':
          $ref: '#/components/responses/CreateYieldRules'
        '202':
          $ref: '#/components/responses/QueueYieldRules'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/yield-rules/{yieldRule}:
    get:
      summary: Get a YieldRule
      tags:
        - YieldRules
      operationId: getYieldRule
      description: |
        Retrieves a single `YieldRule`.
      parameters:
        - $ref: '#/components/parameters/yieldRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowYieldRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update a YieldRule
      tags:
        - YieldRules
      operationId: updateYieldRule
      description: |
        Replaces this rule's definition in full.

        Only this rule changes. Rules created alongside it are independent copies and
        are left untouched, and the offering a rule applies to is fixed at creation.

        When reductions may start is not part of the rule and cannot be changed here.
        That window belongs to the offering and is shared by every rule lowering its
        price, so it is set when a rule is created and changed from the offering.
      parameters:
        - $ref: '#/components/parameters/yieldRule'
      requestBody:
        $ref: '#/components/requestBodies/UpdateYieldRule'
      responses:
        '200':
          $ref: '#/components/responses/ShowYieldRule'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete a YieldRule
      tags:
        - YieldRules
      operationId: deleteYieldRule
      description: |
        Deletes a `YieldRule`. Rules created alongside it are unaffected.
      parameters:
        - $ref: '#/components/parameters/yieldRule'
      responses:
        '204':
          description: The yield rule was successfully deleted
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/zones/{zoneId}/copy:
    parameters:
      - $ref: '#/components/parameters/parameters_zoneId-3'
    post:
      summary: Duplicate a Zone
      description: |
        Creates a copy of an existing `Zone`. Any properties supplied in
        the request body are overlaid on the source values, letting you
        rename the copy or move it to a different site without rebuilding
        from scratch. Properties omitted from the body are inherited from
        the original verbatim.

        Requires the `SETTINGS_MANAGE` permission on the target site.
      operationId: copyZone
      tags:
        - Zones
      requestBody:
        description: Properties that should be overridden on the copied zone.
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Zone'
      responses:
        '201':
          $ref: '#/components/responses/ShowZone'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /inventory/orders/{orderId}/preview-email:
    parameters:
      - $ref: '#/components/parameters/orderId'
  /token-info:
    get:
      summary: Get the current bearer token info
      description: |
        Decode the bearer token used to make this request and return
        its standard JWT claims (`aud`, `jti`, `iat`, `nbf`, `exp`,
        `sub`). Useful as an introspection endpoint when a client
        needs to know when its token expires or which user the token
        is currently bound to without parsing the JWT itself.

        The token is verified with Trybe's signing key before the
        claims are returned, so a successful response also confirms
        the token is currently valid. The response only includes the
        six claims listed above; custom claims and private extensions
        are intentionally stripped.
      operationId: getTokenInfo
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/ShowTokenInfo'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/membership-types/{membershipTypeId}/restore:
    parameters:
      - $ref: '#/components/parameters/parameters_membershipTypeId-3'
    post:
      summary: Restore a MembershipType
      description: |
        Restores a soft-deleted `MembershipType` so it can once again be
        selected for new memberships. Partner to `deleteMembershipType`.
      tags:
        - MembershipTypes
      operationId: restoreMembershipType
      responses:
        '200':
          $ref: '#/components/responses/ShowMembershipType'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/queued-jobs/{queuedJobId}:
    parameters:
      - $ref: '#/components/parameters/parameters_queuedJobId'
    get:
      summary: Get the details of a customer queued job
      description: |
        Returns the status and output of a customer-api background job
        that was previously kicked off via a queue-issuing endpoint
        (e.g. the customer list, check-ins, or memberships report
        queues). Poll this endpoint until `status` transitions to
        `complete` or `failed`; `output` then contains the per-job
        result envelope.

        Only the user who enqueued the job can poll it.
      operationId: getCustomerQueuedJob
      tags:
        - Customers
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /sites/{siteId}/credentials:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/express-stripe-dashboard:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/integrations/saml/config:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/integrations/saml/metadata:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/invoices:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /sites/{siteId}/stripe-dashboard:
    parameters:
      - $ref: '#/components/parameters/siteId'
  /customers/customers/{customerId}/barcodes/{barcodeId}/expiry-date:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/barcodeIdPath'
    put:
      summary: Update an Associated Barcode's expiry date
      description: |
        Changes when the given barcode stops being usable for identifying
        the customer at the till and at kiosks. Pass an ISO-8601 datetime
        in `expires_at` to set or extend the expiry, or `null` to clear it
        entirely (the barcode remains valid indefinitely).

        The `expires_at` value must be in the future — barcodes cannot be
        back-dated through this endpoint. The change is audited against the
        customer record (`updated_barcode`) so the previous and new expiry
        are kept in the audit trail.

        Use this instead of recreating the barcode when the underlying
        wearable / wristband stays the same but its lease term changes,
        e.g. when a member renews their pass or a day-spa wristband is
        handed back early.
      tags:
        - Customers
      operationId: updateBarcodeExpiryDate
      requestBody:
        $ref: '#/components/requestBodies/UpdateBarcodeExpiryDate'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerAssociatedBarcode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/{customerId}/barcodes/{barcodeId}/payment-method:
    parameters:
      - $ref: '#/components/parameters/customerIdPath'
      - $ref: '#/components/parameters/barcodeIdPath'
    put:
      summary: Update an Associated Barcode's payment method
      description: |
        Links a `PaymentMethod` to the given barcode (or unlinks the
        current one). When a payment method is attached, charges captured
        via the barcode — typically wristband-based "post-pay" purchases at
        a spa or resort — are funded from that saved card rather than
        requiring the guest to present payment at every till.

        Pass `payment_method_id: null` to detach the current payment
        method; subsequent tap-to-charge attempts on the barcode will then
        be declined or routed to a manual-pay flow depending on the site
        configuration.

        The chosen `PaymentMethod` must belong to the same customer and
        pass server-side validation against the underlying processor (for
        card methods that means the card has to still be valid on the
        customer's processor profile). The change is recorded in the
        customer audit log under `updated_barcode_payment_method`.
      tags:
        - Customers
      operationId: updateBarcodePaymentMethod
      requestBody:
        $ref: '#/components/requestBodies/UpdateBarcodePaymentMethod'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerAssociatedBarcode'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/customers/from-guestline-ref/{guestlineRef}:
    parameters:
      - $ref: '#/components/parameters/guestlineRef'
  /customers/membership-charges:
    get:
      summary: List MembershipCharges
      tags:
        - MembershipCharges
      operationId: listCustomerMembershipCharges
      description: |
        Returns a paginated list of `MembershipCharge`s — the historical
        record of every direct-debit, card or offline payment captured (or
        attempted) against the recurring `Membership`s in the caller's
        organisation.

        Use this to power membership-billing reports, reconcile failed
        payments before retry, or surface a charge history on a customer's
        profile.

        Filters cascade: omitting `status` returns non-pending,
        non-refunded charges (the default reporting view). Pass
        `status=all` to include every charge regardless of state, or pass
        `pending`/`overdue` to scope to the corresponding billing window.
        `site_id` is restricted server-side to the caller's accessible
        sites; passing a `site_id` the caller cannot see returns an empty
        result rather than 403.

        Requesting the response as CSV (`Accept: text/csv`) elevates the
        permission check to `reports.download`; use the companion
        [`queueCustomerMembershipCharges`](#operation/queueCustomerMembershipCharges)
        endpoint for asynchronous CSV exports beyond a few thousand rows.

        Note: an earlier docs revision listed this operation under
        `/shop/membership-charges`. The Laravel controller has always
        lived in customer-api, so `/customers/membership-charges` is the
        correct and canonical path.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/organisation_id'
        - $ref: '#/components/parameters/parameters_membershipId'
        - $ref: '#/components/parameters/parameters_status-16'
        - $ref: '#/components/parameters/billingPeriodFromStart'
        - $ref: '#/components/parameters/billingPeriodFromEnd'
        - $ref: '#/components/parameters/createdAtStart'
        - $ref: '#/components/parameters/createdAtEnd'
        - $ref: '#/components/parameters/amountFrom'
        - $ref: '#/components/parameters/amountTo'
        - $ref: '#/components/parameters/parameters_processor-2'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListMembershipCharges'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/membership-charges/queue:
    get:
      summary: Queue a MembershipCharges export
      tags:
        - MembershipCharges
      operationId: queueCustomerMembershipCharges
      description: |
        Kicks off an asynchronous CSV export of `MembershipCharge`s
        matching the supplied filters. Returns immediately with a
        `QueuedJob` envelope; poll
        [`getCustomerQueuedJob`](#operation/getCustomerQueuedJob) until the
        job transitions to `complete` or `failed`. On success, the job's
        `output` contains a signed download URL for the generated CSV.

        Use this in preference to the synchronous
        [`listCustomerMembershipCharges`](#operation/listCustomerMembershipCharges)
        endpoint when the result set is large (more than a few thousand
        rows) or when the export is intended to be emailed to the
        requesting user — pass `email=true` to have the finished CSV
        delivered as an email attachment instead of (or alongside) the
        pollable download URL.

        Requires the `reports.download` permission on every site whose
        charges fall in scope.

        Note: an earlier docs revision exposed this operation under
        `/shop/membership-charges/queue`. The Laravel controller has
        always lived in customer-api, so `/customers/membership-charges/queue`
        is the correct and canonical path.
      parameters:
        - $ref: '#/components/parameters/parameters_siteId'
        - $ref: '#/components/parameters/organisation_id'
        - $ref: '#/components/parameters/parameters_membershipId'
        - $ref: '#/components/parameters/parameters_status-16'
        - $ref: '#/components/parameters/billingPeriodFromStart'
        - $ref: '#/components/parameters/billingPeriodFromEnd'
        - $ref: '#/components/parameters/createdAtStart'
        - $ref: '#/components/parameters/createdAtEnd'
        - $ref: '#/components/parameters/amountFrom'
        - $ref: '#/components/parameters/amountTo'
        - $ref: '#/components/parameters/parameters_processor-2'
        - $ref: '#/components/parameters/parameters_email-4'
      responses:
        '200':
          $ref: '#/components/responses/QueuedJobResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
  /customers/memberships/{membershipId}/change-end-date:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    get:
      summary: Preview a Membership end-date change
      description: |
        Runs the membership end-date change logic in memory **without
        persisting it** and returns the `Membership` as it would look
        after the move. Use this as a dry-run before calling
        [`actionChangeMembershipEndDate`](#operation/actionChangeMembershipEndDate)
        so the operator can review the downstream impact (cancelled
        pending charges, revised next-billing date, etc.) and confirm
        before committing.

        Pass `end_date` as an ISO-8601 date in `YYYY-MM-DD` format, or
        `null` to preview removing the end date entirely (i.e. converting
        a fixed-term membership to an open-ended one). The supplied
        `end_date` must be strictly after the membership's existing
        `start_date`.

        The response payload matches the regular [`getMembership`](#operation/getMembership)
        shape — fields like `status`, `next_billing_date` and `end_date`
        will reflect the post-change state.
      tags:
        - Memberships
      operationId: getMembershipEndDateChangePreview
      parameters:
        - $ref: '#/components/parameters/endDate'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    post:
      summary: Change a Membership's end date
      description: |
        Applies a previously previewed end-date change to the
        `Membership` and persists it. The semantics match the
        [`getMembershipEndDateChangePreview`](#operation/getMembershipEndDateChangePreview)
        preview — pending charges whose billing period now falls outside
        the membership are cancelled, the next-billing date is
        recalculated, and the membership status is refreshed.

        Pass `end_date: null` to remove an existing end date entirely
        (converting a fixed-term membership to open-ended). Any supplied
        `end_date` must be strictly after the membership's `start_date`.

        Returns the freshly-saved `Membership`.
      tags:
        - Memberships
      operationId: actionChangeMembershipEndDate
      requestBody:
        $ref: '#/components/requestBodies/ChangeMembershipEndDate'
      responses:
        '200':
          $ref: '#/components/responses/ShowMembership'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/memberships/{membershipId}/update-status:
    parameters:
      - $ref: '#/components/parameters/membershipId'
    post:
      summary: Refresh a Membership's status
      description: |
        Recomputes the derived status fields on a `Membership` (`status`
        and `attention_reason`) based on the current state of its
        underlying charges, billing schedule and external mandate. Use
        this when an out-of-band event (a manual database fix, a stuck
        webhook, a payment-provider reconciliation) has left the
        membership in an inconsistent visible state and the operator
        needs to nudge it back into sync.

        The recomputation is deterministic — it derives the new status
        from the membership's existing data, not from external inputs.
        Pass `dry_run=true` to compute the new status without saving;
        `dry_run=false` (the default) persists the recomputed values.

        The response always returns both the previous and the new
        `status` / `attention_reason` so callers can detect whether the
        refresh actually changed anything.
      tags:
        - Memberships
      operationId: actionUpdateMembershipStatus
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipStatus'
      responses:
        '200':
          $ref: '#/components/responses/MembershipStatusChange'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/new-membership:
    get:
      summary: Get new-membership signup details
      description: |
        Returns the data needed to render the public, unauthenticated
        "join a membership" form for a given site: the membership types
        on offer, the public rates under each type, and (if a
        `MembershipSignupToken` is supplied via `token`) the pre-filled
        customer details and / or the single membership type or rate the
        token has been narrowed to.

        Rates include their joining fee, recurring price and a calculated
        pro-rata amount for an immediate signup based on the current
        date — this is what a self-signup checkout page should display
        side-by-side with the recurring price.

        Membership types are filtered to those visible on the supplied
        site's brand and that have at least one public rate (unless a
        `token` overrides the visibility). Membership types without
        public rates are silently omitted; if a `token` is supplied and
        constrains the type or rate, only that subset is returned.

        This endpoint is public — no authentication is required, since
        it powers the storefront's "Become a member" page.
      tags:
        - Memberships
      operationId: getNewMembershipDetails
      security: []
      parameters:
        - $ref: '#/components/parameters/requiredSiteId'
        - $ref: '#/components/parameters/token'
      responses:
        '200':
          $ref: '#/components/responses/NewMembershipDetails'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/ordered-membership-types:
    get:
      summary: List MembershipTypes in display order
      description: |
        Returns a lightweight `{ id, name }` summary of every
        `MembershipType` in the caller's organisation, sorted by the
        organisation-wide display order (the `order` column on the type),
        then by creation time as a tiebreak.

        Use this to power UIs that need to render the type list in the
        operator-chosen order — typically the drag-to-reorder admin
        screen or any storefront component that picks the "first" type to
        feature. For the full `MembershipType` payload (with rates and
        metadata), use [`listMembershipTypes`](#operation/listMembershipTypes)
        instead.
      tags:
        - MembershipTypes
      operationId: listOrderedMembershipTypes
      parameters:
        - $ref: '#/components/parameters/organisation_id'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedMembershipTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    put:
      summary: Reorder MembershipTypes
      description: |
        Persists a new display order for the caller's `MembershipType`s
        by writing the supplied IDs back to each type's `order` column in
        the order they appear in the array. The first ID becomes order
        `0`, the second `1`, and so on.

        The array must contain only IDs the caller is authorised to
        manage; IDs missing from the array keep their current `order`
        value (i.e. the caller can reorder a subset without listing
        every type). Returns the updated ordered list, matching
        [`listOrderedMembershipTypes`](#operation/listOrderedMembershipTypes).
      tags:
        - MembershipTypes
      operationId: updateMembershipTypeOrder
      requestBody:
        $ref: '#/components/requestBodies/UpdateMembershipTypeOrder'
      responses:
        '200':
          $ref: '#/components/responses/ListOrderedMembershipTypes'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /customers/show-marketing-preferences:
    get:
      summary: List public marketing preferences for an organisation
      description: |
        Returns the marketing preferences (e.g. "email me about offers")
        that an organisation has defined for public display on
        unauthenticated signup flows. The response is a stripped-down
        projection — only the preference ID and display text — so the
        payload is safe to expose on a public webpage.

        Use this to populate the consent checkboxes on a guest-facing
        signup form before the customer has any login credentials.
        Once the customer registers, switch to
        [`listCustomerMarketingPreferences`](#operation/listCustomerMarketingPreferences)
        to read or update their personal opt-in state.

        This endpoint is public — no authentication is required.
      tags:
        - MarketingPreferences
      operationId: listPublicMarketingPreferences
      security: []
      parameters:
        - $ref: '#/components/parameters/parameters_organisationId-4'
      responses:
        '200':
          $ref: '#/components/responses/ListPublicMarketingPreferences'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /customers/user:
    get:
      summary: Get the current user
      description: |
        Returns the authenticated `User` derived from the bearer token on
        the request — i.e. a "whoami" probe for confirming credentials
        are valid and inspecting the caller's identity, organisation and
        site access.

        Although the endpoint is mounted under the `api-public`
        middleware (no auth required for the route to resolve), the
        response body is meaningful only when a bearer token is
        supplied — without one, the body is `null`. Use this in clients
        that need to test "is my token still good?" without committing
        to a heavier authenticated request.
      tags:
        - Users
      operationId: getCurrentUser
      security: []
      responses:
        '200':
          description: The current user, or `null` if the request is unauthenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
  /shop/customers/customer-segments:
    get:
      summary: List CustomerSegments
      description: |
        Returns a paginated list of `CustomerSegment`s for the given site.
      tags:
        - CustomerSegments
      operationId: listCustomerSegments
      parameters:
        - $ref: '#/components/parameters/parameters_site_id-3'
        - $ref: '#/components/parameters/parameters_query-21'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerSegments'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create CustomerSegment
      description: |
        Creates a new `CustomerSegment` for the given site.
      tags:
        - CustomerSegments
      operationId: createCustomerSegment
      requestBody:
        $ref: '#/components/requestBodies/CreateCustomerSegment'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomerSegment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/customer-segments/{customerSegmentId}:
    parameters:
      - $ref: '#/components/parameters/customerSegmentId'
    get:
      summary: Get CustomerSegment
      description: |
        Returns the `CustomerSegment` with the given ID.
      tags:
        - CustomerSegments
      operationId: getCustomerSegment
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerSegment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update CustomerSegment
      description: |
        Updates the given `CustomerSegment`.
      tags:
        - CustomerSegments
      operationId: updateCustomerSegment
      requestBody:
        $ref: '#/components/requestBodies/UpdateCustomerSegment'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerSegment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete CustomerSegment
      description: |
        Soft-deletes the given `CustomerSegment`. Existing segment members are unaffected,
        but the segment can no longer be used for campaigns. Use the companion
        `restoreCustomerSegment` endpoint to undo.
      tags:
        - CustomerSegments
      operationId: deleteCustomerSegment
      responses:
        '204':
          description: The `CustomerSegment` was successfully soft-deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/customer-segments/{customerSegmentId}/restore:
    parameters:
      - $ref: '#/components/parameters/customerSegmentId'
    post:
      summary: Restore CustomerSegment
      description: |
        Restores a soft-deleted `CustomerSegment` so it can once again be used for campaigns.
        Partner to `deleteCustomerSegment`.
      tags:
        - CustomerSegments
      operationId: restoreCustomerSegment
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerSegment'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/customer-segments/{customerSegmentId}/members:
    parameters:
      - $ref: '#/components/parameters/customerSegmentId'
    get:
      summary: List CustomerSegmentMembers
      description: |
        Returns a paginated list of members belonging to the given `CustomerSegment`.
      tags:
        - CustomerSegmentMembers
      operationId: listCustomerSegmentMembers
      parameters:
        - $ref: '#/components/parameters/parameters_query-22'
        - $ref: '#/components/parameters/subscribed'
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
      responses:
        '200':
          $ref: '#/components/responses/ListCustomerSegmentMembers'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Add CustomerSegmentMember
      description: |
        Adds a customer to the given `CustomerSegment`.
      tags:
        - CustomerSegmentMembers
      operationId: createCustomerSegmentMember
      requestBody:
        $ref: '#/components/requestBodies/AddCustomerSegmentMember'
      responses:
        '201':
          $ref: '#/components/responses/ShowCustomerSegmentMember'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/customer-segments/{customerSegmentId}/members/{memberId}:
    parameters:
      - $ref: '#/components/parameters/customerSegmentId'
      - $ref: '#/components/parameters/memberId'
    get:
      summary: Get CustomerSegmentMember
      description: |
        Returns the `CustomerSegmentMember` with the given ID.
      tags:
        - CustomerSegmentMembers
      operationId: getCustomerSegmentMember
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerSegmentMember'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update CustomerSegmentMember
      description: |
        Updates the subscription state of the given segment member.
      tags:
        - CustomerSegmentMembers
      operationId: updateCustomerSegmentMember
      requestBody:
        $ref: '#/components/requestBodies/UpdateCustomerSegmentMember'
      responses:
        '200':
          $ref: '#/components/responses/ShowCustomerSegmentMember'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Remove CustomerSegmentMember
      description: |
        Removes a customer from the given `CustomerSegment`.
      tags:
        - CustomerSegmentMembers
      operationId: deleteCustomerSegmentMember
      responses:
        '204':
          description: The customer was successfully removed from the segment.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/campaigns:
    get:
      summary: List Campaigns
      description: |
        Returns a paginated list of `Campaign`s for the given site.
      tags:
        - Campaigns
      operationId: listCampaigns
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_site_id-4'
        - $ref: '#/components/parameters/parameters_query-23'
        - $ref: '#/components/parameters/parameters_sort-6'
        - $ref: '#/components/parameters/scheduled_at_from'
        - $ref: '#/components/parameters/scheduled_at_to'
        - $ref: '#/components/parameters/sent_at_from'
        - $ref: '#/components/parameters/sent_at_to'
      responses:
        '200':
          $ref: '#/components/responses/ListCampaigns'
        '401':
          $ref: '#/components/responses/Unauthenticated'
    post:
      summary: Create Campaign
      description: |
        Creates a new `Campaign` for the given site.
      tags:
        - Campaigns
      operationId: createCampaign
      requestBody:
        $ref: '#/components/requestBodies/CreateCampaign'
      responses:
        '201':
          $ref: '#/components/responses/ShowCampaign'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/campaigns/{campaignId}:
    parameters:
      - $ref: '#/components/parameters/campaignId'
    get:
      summary: Get Campaign
      description: |
        Returns the `Campaign` with the given ID.
      tags:
        - Campaigns
      operationId: getCampaign
      responses:
        '200':
          $ref: '#/components/responses/ShowCampaign'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update Campaign
      description: |
        Updates the given `Campaign`.
      tags:
        - Campaigns
      operationId: updateCampaign
      requestBody:
        $ref: '#/components/requestBodies/UpdateCampaign'
      responses:
        '200':
          $ref: '#/components/responses/ShowCampaign'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete Campaign
      description: |
        Soft-deletes the given `Campaign`. Use the companion `restoreCampaign` endpoint to undo.
      tags:
        - Campaigns
      operationId: deleteCampaign
      responses:
        '204':
          description: The `Campaign` was successfully soft-deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/campaigns/{campaignId}/copy:
    parameters:
      - $ref: '#/components/parameters/campaignId'
    post:
      summary: Copy Campaign
      description: |
        Creates a copy of the given `Campaign`, duplicating its segment and content
        records. The copy is created in an unsent state with no `scheduled_at` or
        `sent_at` values. Optionally provide a `name` for the copy; defaults to the
        original campaign's name if omitted.
      tags:
        - Campaigns
      operationId: copyCampaign
      requestBody:
        content:
          application/json:
            schema:
              title: CopyCampaign
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  description: The display name for the copied campaign. Defaults to the original campaign's name if not provided.
                  example: Summer Promotion 2024 (Copy)
      responses:
        '201':
          $ref: '#/components/responses/ShowCampaign'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/campaigns/{campaignId}/send:
    parameters:
      - $ref: '#/components/parameters/campaignId'
    post:
      summary: Send Campaign
      description: |
        Queues the given `Campaign` for sending to all subscribed members of its
        associated `CustomerSegment`. Members with a non-null `unsubscribed_at` are
        excluded. Individual `CampaignSend` records are created for each recipient
        and processed asynchronously.

        The `CampaignContent` used for each recipient's `CampaignSend` is selected
        based on the customer's `preferred_locale`, falling back to the site's
        locale if no `CampaignContent` exists for the customer's preferred locale.

        Returns `202 Accepted` immediately; use the `listCampaignSends` endpoint
        to track delivery progress.
      tags:
        - Campaigns
      operationId: actionSendCampaign
      responses:
        '202':
          description: The campaign has been queued for sending.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/campaigns/{campaignId}/restore:
    parameters:
      - $ref: '#/components/parameters/campaignId'
    post:
      summary: Restore Campaign
      description: |
        Restores a soft-deleted `Campaign`. Partner to `deleteCampaign`.
      tags:
        - Campaigns
      operationId: restoreCampaign
      responses:
        '200':
          $ref: '#/components/responses/ShowCampaign'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/campaigns/{campaignId}/contents:
    parameters:
      - $ref: '#/components/parameters/campaignId'
    get:
      summary: List CampaignContents
      description: |
        Returns a paginated list of content records for the given `Campaign`.
      tags:
        - Campaigns
      operationId: listCampaignContents
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_locale'
        - $ref: '#/components/parameters/parameters_query-24'
      responses:
        '200':
          $ref: '#/components/responses/ListCampaignContents'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    post:
      summary: Create CampaignContent
      description: |
        Creates a new content record for the given `Campaign`.
      tags:
        - Campaigns
      operationId: createCampaignContent
      requestBody:
        $ref: '#/components/requestBodies/CreateCampaignContent'
      responses:
        '201':
          $ref: '#/components/responses/ShowCampaignContent'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/campaigns/{campaignId}/contents/{contentId}:
    parameters:
      - $ref: '#/components/parameters/campaignId'
      - $ref: '#/components/parameters/contentId'
    get:
      summary: Get CampaignContent
      description: |
        Returns the `CampaignContent` with the given ID.
      tags:
        - Campaigns
      operationId: getCampaignContent
      responses:
        '200':
          $ref: '#/components/responses/ShowCampaignContent'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
    put:
      summary: Update CampaignContent
      description: |
        Updates the given `CampaignContent`.
      tags:
        - Campaigns
      operationId: updateCampaignContent
      requestBody:
        $ref: '#/components/requestBodies/UpdateCampaignContent'
      responses:
        '200':
          $ref: '#/components/responses/ShowCampaignContent'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    delete:
      summary: Delete CampaignContent
      description: |
        Permanently deletes the given `CampaignContent`.
      tags:
        - Campaigns
      operationId: deleteCampaignContent
      responses:
        '204':
          description: The `CampaignContent` was successfully deleted.
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/campaigns/{campaignId}/contents/{contentId}/preview:
    parameters:
      - $ref: '#/components/parameters/campaignId'
      - $ref: '#/components/parameters/contentId'
    post:
      summary: Preview CampaignContent
      description: |
        Renders a preview of the given `CampaignContent`, substituting the `content`
        body with the value supplied in the request body. Returns the rendered HTML as a plain
        string response.
      tags:
        - Campaigns
      operationId: actionPreviewCampaignContent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              title: PreviewCampaignContent
              type: object
              additionalProperties: false
              properties:
                content:
                  type: string
                  description: The Markdown email body content to render.
                  example: '**Hi there!** We have a special offer just for you.'
                subject:
                  type: string
                  description: The email subject line to use in the preview.
                  example: Exclusive summer offer just for you
              required:
                - content
      responses:
        '200':
          description: The rendered HTML preview of the campaign content.
          content:
            text/html:
              schema:
                type: string
                example: <p>Hi there! We have a special offer just for you.</p>
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
  /shop/customers/campaigns/{campaignId}/sends:
    parameters:
      - $ref: '#/components/parameters/campaignId'
    get:
      summary: List CampaignSends
      description: |
        Returns a paginated list of send records for the given `Campaign`.
      tags:
        - Campaigns
      operationId: listCampaignSends
      parameters:
        - $ref: '#/components/parameters/pageParam'
        - $ref: '#/components/parameters/perPageParam'
        - $ref: '#/components/parameters/parameters_query-25'
        - $ref: '#/components/parameters/sent'
        - $ref: '#/components/parameters/failed'
        - $ref: '#/components/parameters/bounced'
      responses:
        '200':
          $ref: '#/components/responses/ListCampaignSends'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
  /shop/customers/campaigns/{campaignId}/sends/{sendId}:
    parameters:
      - $ref: '#/components/parameters/campaignId'
      - $ref: '#/components/parameters/sendId'
    get:
      summary: Get CampaignSend
      description: |
        Returns the `CampaignSend` with the given ID. Requesting with an
        `Accept: text/html` header returns the rendered HTML body of the sent
        email instead, and responds with `404` if the send has no stored content
        to render.
      tags:
        - Campaigns
      operationId: getCampaignSend
      responses:
        '200':
          $ref: '#/components/responses/ShowCampaignSend'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/EntityNotFound'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT Bearer token authentication
  parameters:
    siteId:
      name: siteId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the site
    invoiceId:
      name: invoiceId
      in: path
      description: The ID of the invoice
      required: true
      schema:
        type: string
    userId:
      name: userId
      in: path
      description: |
        Identifier of the admin user. Returned from `listAdminUsers` and
        `createAdminUser`; used for updates, password resets, organisation
        status changes, and managing site access.
      required: true
      schema:
        type: string
        format: uuid
    parameters_userId:
      name: userId
      in: path
      description: |
        Identifier of the API user. Returned from `listAdminApiUsers` and
        `createAdminApiUser`; used to update the user, regenerate its
        token, manage its site access, or fetch its usage report.
      required: true
      schema:
        type: string
        format: uuid
    pageParam:
      in: query
      name: page
      required: false
      schema:
        type: integer
      description: The page to retrieve results from
      example: 1
    perPageParam:
      in: query
      name: per_page
      required: false
      schema:
        type: integer
      description: The number of results to return per page
      example: 15
    parameters_siteId:
      in: query
      name: site_id
      required: false
      schema:
        type: string
      description: Filter results by the site they belong to
    organisationId:
      in: query
      name: organisation_id
      required: false
      schema:
        type: string
        format: uuid
      description: Filter users by the organisation they belong to
    sort:
      in: query
      name: sort
      description: The field to order results by.
      required: false
      schema:
        type: string
    query:
      in: query
      name: query
      required: false
      schema:
        type: string
      description: Filter users by their name or email
    includeInactive:
      in: query
      name: include_inactive
      required: false
      description: Filter users according to whether they are active or not.
      schema:
        type: boolean
    parameters_userId-2:
      name: userId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the user
    parameters_query:
      name: query
      in: query
      required: false
      schema:
        type: string
      description: Filter results by name or ID.
    sortByQuery:
      in: query
      name: sort_by
      required: false
      description: The field to sort the results by.
      schema:
        type: string
    sortByDirection:
      name: sort_by_direction
      in: query
      required: false
      schema:
        type: string
        enum:
          - asc
          - desc
      description: The direction in which to sort to the response.
    date:
      name: date
      in: query
      required: false
      description: The date to fetch events for
      schema:
        type: string
        format: date
      example: '2022-01-15'
    events:
      name: events
      in: query
      required: false
      description: |
        A comma-separated list of event keys and event types to return.
        The format is {event_type}..{event_key}, for example:
        `appointment..1234_5678,session..5678_9012`
      schema:
        type: string
    includeCustomers:
      name: include_customers
      in: query
      required: false
      description: Whether to include a `CalendarEvent`s associated customers.
      schema:
        type: string
        format: boolean
    includePayments:
      name: include_payments
      in: query
      required: false
      description: Whether to include a `CalendarEvent`s associated payments.
      schema:
        type: string
        format: boolean
    includeSessionBookings:
      name: include_session_bookings
      in: query
      required: false
      description: Whether to include a `CalendarEvent`s associated bookings.
      schema:
        type: string
        format: boolean
    viewType:
      name: view_type
      in: query
      required: false
      description: |
        The view type (resource) to return events for. If specified, an event object will
        be returned for each resource of this type in the event.
      schema:
        type: string
        enum:
          - area
          - practitioner
          - room
    zoneId:
      name: zone_id
      in: query
      required: false
      description: The zone ID to filter events for.
      schema:
        type: string
    requiredSiteId:
      in: query
      name: site_id
      required: true
      schema:
        type: string
      description: Filter results by the site they belong to
    parameters_date:
      name: date
      in: query
      description: A date string to retrieve results for
      required: false
      schema:
        type: string
        format: date
        example: '2000-01-01'
    dateFrom:
      name: dateFrom
      in: query
      description: A date string to retrieve results from
      required: false
      schema:
        type: string
        format: date
        example: '2000-01-01'
    dateTo:
      name: dateTo
      in: query
      description: A date string to retrieve results to
      required: false
      schema:
        type: string
        format: date
        example: '2000-01-01'
    calendarNoteId:
      name: calendarNoteId
      in: path
      required: true
      description: The unique identifier of the `CalendarNote`.
      schema:
        type: string
        format: object-id
    parameters_siteId-2:
      in: path
      name: siteId
      schema:
        type: string
        format: uuid
      description: The ID of the site
    basketId:
      name: basketId
      description: The unique identifier of the `Basket`.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    offeringId:
      name: offeringId
      description: The ID of the `Offering`.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    offeringType:
      name: offeringType
      description: The type of `Offering`.
      in: path
      required: true
      schema:
        $ref: '#/components/schemas/OfferingType'
    terminalRequestId:
      in: path
      name: terminalRequestId
      required: true
      description: The ID of the `TerminalRequest`
      schema:
        type: string
        format: object-id
    paymentId:
      in: path
      name: paymentId
      required: true
      description: The ID of the `CardTokenisationRequest`
      schema:
        type: string
        format: object-id
    dateFromQuery:
      in: query
      name: date_from
      required: false
      description: |
        Restrict results to those on or after this date, ISO-8601 `YYYY-MM-DD`.
      schema:
        type: string
        format: date
    dateToQuery:
      in: query
      name: date_to
      required: false
      description: |
        Restrict results to those on or before this date, ISO-8601 `YYYY-MM-DD`.
      schema:
        type: string
        format: date
    orderSubmittedAtFrom:
      name: order_submitted_at_from
      description: the order submitted date to fetch appointments from
      in: query
      schema:
        type: string
        format: date
      example: '2019-01-15T12:00:00+01:00'
    orderSubmittedAtTo:
      name: order_submitted_at_to
      description: the order submitted date to fetch appointments to
      in: query
      schema:
        type: string
        format: date
      example: '2019-01-15T12:00:00+01:00'
    practitionerId:
      name: practitioner_id
      description: A comma separated string of practitioner ids to fetch bookings for
      in: query
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8767
    roomId:
      name: room_id
      description: A comma separated string of room ids to fetch bookings for
      in: query
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8768
    parameters_zoneId:
      name: zone_id
      description: A comma separated string of zone ids to fetch bookings for
      in: query
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8768
    appointmentId:
      name: appointmentId
      in: path
      required: true
      description: |
        The unique identifier of the `Appointment`. An appointment is a
        booking of an `AppointmentType` against one or more `Practitioner`s
        and (optionally) a `Room`. The ID is the MongoDB ObjectID that the
        appointment was assigned when it was created via the `Basket`.
      schema:
        type: string
        format: object-id
      example: 5e932c0901d210625e3a8766
    areaBookingId:
      name: areaBookingId
      in: path
      required: true
      description: |
        The unique identifier of the `AreaBooking`. An area booking is a
        reservation of one or more `BookableArea`s for a contiguous period
        of time, typically created via the basket as part of an order.
      schema:
        type: string
        format: object-id
      example: 5e932c0901d210625e3a8766
    siteIdFilter:
      name: site_id
      in: query
      description: Filter the list of voucher codes to a single site.
      schema:
        type: string
        format: uuid
    code:
      name: code
      in: query
      description: |
        Partial, case-insensitive substring match on the voucher
        redemption `code`.
      schema:
        type: string
      example: ABC123
    status:
      name: status
      in: query
      description: |
        Filter by voucher code status. Pass multiple statuses as a
        comma-separated list.
      explode: false
      schema:
        type: array
        items:
          type: string
          enum:
            - unredeemed
            - partially_redeemed
            - redeemed
            - revoked
            - expired
      example: unredeemed,partially_redeemed
    amount:
      name: amount
      in: query
      description: |
        Filter by voucher amount. Supports comparison operators
        (`>1000`, `<5000`, `>=2500`, `<=2500`, `=1000`) — values are in
        the smallest unit of the voucher's currency.
      schema:
        type: string
      example: '>5000'
    balance:
      name: balance
      in: query
      description: |
        Filter by remaining voucher balance. Supports the same comparison
        operators as `amount`.
      schema:
        type: string
      example: '>0'
    createdSince:
      name: created_since
      in: query
      description: Filter for voucher codes created on or after this date-time.
      schema:
        type: string
        format: date-time
      example: '2026-01-01T00:00:00+00:00'
    voucherTypeId:
      name: voucher_type_id
      in: query
      description: |
        Filter to voucher codes whose `voucher_type_id` matches one of the
        given IDs.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    expiredRangeFrom:
      name: expired_range_from
      in: query
      description: |
        Filter to voucher codes whose `valid_to_date` is on or after this
        date.
      schema:
        type: string
        format: date
    expiredRangeTo:
      name: expired_range_to
      in: query
      description: |
        Filter to voucher codes whose `valid_to_date` is before this date.
      schema:
        type: string
        format: date
    fulfillmentStatus:
      name: fulfillment_status
      in: query
      description: |
        Filter by fulfilment status — `needs_dispatching` for vouchers
        awaiting physical delivery, `dispatched` once sent, `not_required`
        for digital deliveries.
      schema:
        type: string
    voucherCodeId:
      name: voucherCodeId
      in: path
      required: true
      description: |
        The unique identifier of the `VoucherCode`. Each issued voucher
        has its own `VoucherCode` record holding the redemption code,
        balance, validity window, and fulfilment state.
      schema:
        type: string
        format: object-id
      example: 5e932c0901d210625e3a8766
    archivedQuery:
      in: query
      name: archived
      required: false
      description: |
        Whether to include archived resources in the response. When `true`,
        archived resources are returned; when `false` or omitted, only
        non-archived resources are returned.
      schema:
        type: boolean
    parameters_practitionerId:
      in: query
      name: practitioner_id
      required: false
      description: |
        Filter results to appointment types that include the given practitioner
        in their `practitioner_ids`. Comma-separate to OR multiple practitioners
        (e.g. `practitioner_id=abc,def`).
      schema:
        type: string
      example: 5f1234567890abcdef123456
    categoryId:
      in: query
      name: category_id
      required: false
      description: |
        Filter results to appointment types that include the given category
        in their `category_ids`. Comma-separate to OR multiple categories.
      schema:
        type: string
      example: 5f1234567890abcdef123456
    appointmentTypeId:
      name: appointmentTypeId
      description: The ID of the appointment type.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    availabilityRuleId:
      name: availabilityRuleId
      in: path
      required: true
      description: The unique identifier of the availability rule.
      schema:
        type: string
        format: object-id
    weekdays:
      in: query
      name: weekdays
      description: Filter for price rules that are apply on any of the given weekdays.
      required: false
      schema:
        type: array
        items:
          type: string
      explode: false
    priceRuleId:
      name: priceRuleId
      in: path
      required: true
      description: The unique identifier of the price rule.
      schema:
        type: string
        format: object-id
    locale:
      name: locale
      in: path
      required: true
      description: |
        A supported locale code (e.g. `fr`, `en_GB`). The bare `en` locale is not accepted — base
        English strings are stored directly on the offering's `name` and `description` fields.
        Regional English variants such as `en_GB` and `en_US` are valid.
      schema:
        type: string
        example: fr
    parameters_categoryId:
      in: query
      name: category_id
      required: false
      description: |
        Filter results to area booking types that include the given category
        in their `category_ids`. Comma-separate to OR multiple categories.
      schema:
        type: string
      example: 5f1234567890abcdef123456
    areaBookingTypeId:
      name: areaBookingTypeId
      description: The ID of the area booking type
      in: path
      required: true
      schema:
        type: string
        format: object-id
    couponCodeId:
      name: coupon
      description: The unique identifier of the `CouponCode` to remove from the basket.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    customerCreditId:
      name: customerCredit
      description: The unique identifier of the `CustomerCredit` to remove from the basket.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    itemId:
      name: item
      description: The unique identifier of the `BasketItem`.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    packageItemId:
      name: packageItem
      description: The unique identifier of the `BasketPackageItem`.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    parameters_paymentId:
      name: payment
      description: The unique identifier of the `Payment` to remove from the basket.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    parameters_voucherCodeId:
      name: voucher
      description: The unique identifier of the `VoucherCode` to remove from the basket.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    bookableAreaId:
      name: bookableAreaId
      description: The ID of the bookable area.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    courseTypeId:
      name: courseTypeId
      description: The ID of a `CourseType` offering type.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    parameters_query-2:
      in: query
      name: query
      required: false
      schema:
        type: string
      description: A general search query to match against customer fields.
    source:
      in: query
      name: source
      required: false
      schema:
        type: array
        items:
          type: string
      explode: false
      description: Choose which sources to include in the search.
    firstName:
      in: query
      name: first_name
      required: false
      schema:
        type: string
      description: Filter by first name.
    lastName:
      in: query
      name: last_name
      required: false
      schema:
        type: string
      description: Filter by last name.
    email:
      in: query
      name: email
      required: false
      schema:
        type: string
      description: Filter by email address.
    customerIdPath:
      name: customerId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: |
        The unique identifier of the customer this operation is scoped to.
        Customer IDs are stable across renames and email changes; treat them
        as opaque strings even though the underlying format is a UUID.
    equipmentId:
      name: equipmentId
      in: path
      required: true
      description: The unique identifier of the `Equipment`.
      schema:
        type: string
        format: object-id
    escPosConnector:
      in: path
      name: escPosConnector
      description: The ID of the EscPos Connector
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-3:
      in: query
      name: site_id
      description: Filter the list of discount types by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_query-3:
      name: query
      in: query
      description: |
        A search query to filter discount types by. This will search the discount type code.
      required: false
      schema:
        type: string
    applicableFor:
      name: applicable_for
      in: query
      description: |
        Filter the list of discount types by where they are able to be applied.
      required: false
      schema:
        type: string
        enum:
          - app_only
          - app_and_booking_engine
    discountType:
      in: path
      name: discountType
      description: The ID of the `DiscountType`
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-4:
      in: query
      name: site_id
      description: Get external IDs for the given site.
      required: false
      schema:
        type: string
        format: uuid
    externalIdType:
      in: path
      name: externalIdType
      description: The ID of the `ExternalIdType`
      required: true
      schema:
        type: string
        format: mongo-id
    parameters_siteId-5:
      in: path
      name: siteId
      description: The ID of the `Site`
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-6:
      in: query
      name: site_id
      required: true
      schema:
        type: string
        format: uuid
      description: Get hotel room types for this given site ID.
    externalSource:
      in: query
      name: external_source
      required: false
      schema:
        type: string
      description: Only include hotel rooms from this source.
    hotelRoomTypeId:
      in: path
      name: hotelRoomTypeId
      description: The ID of the hotel room type.
      required: true
      schema:
        type: string
        format: object-id
    parameters_appointmentTypeId:
      in: path
      name: appointmentTypeId
      description: The ID of the appointment type the enquiry is for.
      schema:
        type: string
        format: mongo-id
    dateTimeFrom:
      in: query
      name: date_time_from
      description: The earliest time the appointment could start.
      required: true
      schema:
        type: string
    dateTimeTo:
      in: query
      name: date_time_to
      description: The latest time the appointment could end.
      required: true
      schema:
        type: string
    tableReservationTypeId:
      in: path
      name: tableReservationTypeId
      description: The ID of the `TableReservationType`.
      required: true
      schema:
        type: string
        format: object-id
    parameters_date-2:
      in: query
      name: date
      description: The date the reservation is for.
      required: true
      schema:
        type: string
        format: date
    numGuests:
      in: query
      name: num_guests
      description: The number of guests the reservation is for.
      required: true
      schema:
        type: string
        format: integer
    importId:
      in: path
      name: importId
      description: The ID of the import.
      required: true
      schema:
        type: string
        format: uuid
    type:
      name: type
      description: Filter sections by type. Omitting this parameter returns sections where type is null.
      in: query
      required: false
      schema:
        type: string
        enum:
          - mandatory
    intakeFormSectionId:
      name: intakeFormSectionId
      description: The ID of the `IntakeFormSection`.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    parameters_siteId-7:
      name: site_id
      description: The ID of the `Site` associated with the `IntakeFormQuestion`.
      in: query
      required: true
      schema:
        type: string
        format: object-id
    parameters_siteId-8:
      in: path
      name: siteId
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the site to retrieve membership type offerings for.
    membershipTypeId:
      in: path
      name: membershipTypeId
      description: The ID of the Membership Type to retrieve the revenue centre for.
      required: true
      schema:
        type: string
        format: uuid
    parameters_offeringType:
      name: offering_type
      description: Filter by specific offering types.
      in: query
      required: false
      schema:
        type: array
        items:
          $ref: '#/components/schemas/OfferingType'
          nullable: true
      explode: false
    parameters_practitionerId-2:
      name: practitioner_id
      description: Filter by specific practitioner IDs.
      in: query
      required: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_query-4:
      name: query
      description: Provide a search query to match offerings against.
      in: query
      required: false
      schema:
        type: string
    parameters_siteId-9:
      name: site_id
      description: The site ID the offerings belong to.
      in: query
      required: true
      schema:
        type: string
        format: uuid
    parameters_sort:
      in: query
      name: sort
      description: How to order the results.
      required: false
      schema:
        type: string
        enum:
          - name
    parameters_categoryId-2:
      in: query
      name: category_id
      required: false
      description: |
        Filter results to packages that include the given category in their
        `category_ids`. Comma-separate to OR multiple categories
        (e.g. `category_id=5e932c0901d210625e3a8766,5e932c0901d210625e3a8767`).
      schema:
        type: string
      example: 5e932c0901d210625e3a8766
    includeOptionOfferings:
      in: query
      name: include_option_offerings
      required: false
      description: |
        When `true`, each `Package`'s `item_choices[].options[].offering` is
        populated with a hydrated `PackageShopOffering` (name, price, image,
        etc.) — useful when rendering the package contents on an admin page
        without making a follow-up request per option. Defaults to `false`
        to keep responses small.
      schema:
        type: boolean
      example: true
    packageId:
      in: path
      name: packageId
      schema:
        type: string
        format: object-id
      description: The ID of the package
    basketItemId:
      in: query
      name: basketItemId
      schema:
        type: string
        format: object-id
      description: The ID of the basket item associated with the package. If provided, the returned package will include additional fields relevant to the basket item.
    itemChoiceId:
      name: itemChoiceId
      in: path
      required: true
      description: The unique identifier of the item choice (also known as a choice group) within the package.
      schema:
        type: string
        format: object-id
    mappingId:
      in: path
      name: mappingId
      description: The ID of the mapping
      required: true
      schema:
        type: string
        format: object-id
    parameters_query-5:
      in: query
      name: query
      description: Filter for products where the name matches a search query.
      required: false
      schema:
        type: string
    productCode:
      in: query
      name: product_code
      description: Filter for products with the specified product code. Partial matches can be searched by using a * wildcard.
      required: false
      schema:
        type: string
    inventoryCategoryId:
      in: query
      name: inventory_category_id
      description: Filter for products that belong to one of the specified inventory categories.
      required: false
      schema:
        type: array
        items:
          type: string
      explode: false
    productId:
      in: path
      name: productId
      schema:
        type: string
        format: object-id
      description: The ID of the product
    parameters_roomId:
      name: roomId
      description: The ID of the room.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    parameters_siteId-10:
      in: query
      name: site_id
      description: Restrict the report to order items belonging to the given site. Omit to include items from every site the caller's API key can access; the response groups them under their own `site_id` field.
      schema:
        type: string
        format: uuid
    orderLabel:
      in: query
      name: order_label
      description: A comma-separated list of order labels IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128c05a210879a60ac1af,69c128c05a210879a60ac1ae
      deprecated: true
    orderLabelIds:
      in: query
      name: order_label_ids
      description: A comma-separated list of order labels IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128c05a210879a60ac1af,69c128c05a210879a60ac1ae
    salesChannelId:
      in: query
      name: sales_channel_id
      description: A comma-separated list of sales channel IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128bf5a210879a60ac186,69c128bf5a210879a60ac187,69c128bf5a210879a60ac188
      deprecated: true
    salesChannelIds:
      in: query
      name: sales_channel_ids
      description: A comma-separated list of sales channel IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128bf5a210879a60ac186,69c128bf5a210879a60ac187,69c128bf5a210879a60ac188
    parameters_offeringId:
      in: query
      name: offering_id
      description: A comma-separated list of offering IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8767
      deprecated: true
    offeringIds:
      in: query
      name: offering_ids
      description: A comma-separated list of offering IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8767
    parameters_offeringType-2:
      in: query
      name: offering_type
      description: A comma-separated list of item types to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      example: appointment,area_booking
      deprecated: true
    offeringTypes:
      in: query
      name: offering_types
      description: A comma-separated list of item types to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      example: appointment,area_booking
    offeringCategory:
      in: query
      name: offering_category
      description: Filter by the offering's category.
      schema:
        type: string
      deprecated: true
    offeringCategoryIds:
      in: query
      name: offering_category_ids
      description: A comma-separated list of offering category ids to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128bf5a210879a60ac18f,69c128c05a210879a60ac231
    parameters_status:
      in: query
      name: status
      description: Filter by the status of the item.
      schema:
        type: string
      example: submitted
      deprecated: true
    statuses:
      in: query
      name: statuses
      description: A comma-separated list of statuses to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      example: confirmed
    orderStatus:
      in: query
      name: order_status
      description: A comma-separated list of order statuses to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      example: settled
      deprecated: true
    orderStatuses:
      in: query
      name: order_statuses
      description: A comma-separated list of order statuses to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      example: settled
    revenueDateFrom:
      in: query
      name: revenue_date_from
      description: Filter on items with an order revenue date on or after this date.
      schema:
        type: string
        format: date
      example: '2026-01-15'
    revenueDateTo:
      in: query
      name: revenue_date_to
      description: Filter on items with an order revenue date on or before this date.
      schema:
        type: string
        format: date
      example: '2026-01-15'
    parameters_dateFrom:
      in: query
      name: date_from
      description: Filter on items with a start time on or after this date.
      schema:
        type: string
        format: date-time
      example: '2026-04-01T00:00:00Z'
    parameters_dateTo:
      in: query
      name: date_to
      description: Filter on items with a start time on or before this date.
      schema:
        type: string
        format: date-time
      example: '2026-04-01T00:00:00Z'
    parameters_orderSubmittedAtFrom:
      in: query
      name: order_submitted_at_from
      description: Filter on orders with a submitted date on or after this time.
      schema:
        type: string
        format: date-time
      example: '2026-04-01T00:00:00Z'
    parameters_orderSubmittedAtTo:
      in: query
      name: order_submitted_at_to
      description: Filter on orders with a submitted date before this time.
      schema:
        type: string
        format: date-time
      example: '2026-04-01T00:00:00Z'
    itemDateFrom:
      in: query
      name: item_date_from
      description: Filter on items which are booked in for on or after this date.
      schema:
        type: string
        format: date
      example: '2026-04-01'
    itemDateTo:
      in: query
      name: item_date_to
      description: Filter on items which are booked in for before this date.
      schema:
        type: string
        format: date
      example: '2026-04-01'
    parameters_categoryId-3:
      in: query
      name: category_id
      description: A comma-separated list of category IDs to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      deprecated: true
    categoryIds:
      in: query
      name: category_ids
      description: A comma-separated list of stock category IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      example: a1706517-e41f-4153-8d6b-35b7eaa9fa6e
    brandIds:
      in: query
      name: brand_ids
      description: A comma-separated list of stock brand IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      example: a17246cf-2cf3-4bf9-8b8b-16a80be860a3,a16ecf67-8c06-4e27-9ef5-f024d8a00914
    revenueCentres:
      in: query
      name: revenue_centres
      description: A comma-separated list of revenue centre names to filter on.
      schema:
        type: array
        items:
          type: string
      explode: false
      example: deposit
    soldById:
      in: query
      name: sold_by_id
      description: A comma-separated list of user IDs to filter for items sold by that user.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      example: a11862ac-37e9-4781-aaf1-b43ca42079f7,a11862ac-380b-464c-a45d-35c2bd7b402f,a11862ac-369e-4552-9349-91538f9a42c3
      deprecated: true
    soldByIds:
      in: query
      name: sold_by_ids
      description: A comma-separated list of user IDs to filter for items sold by that user.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      example: a11862ac-37e9-4781-aaf1-b43ca42079f7,a11862ac-380b-464c-a45d-35c2bd7b402f,a11862ac-369e-4552-9349-91538f9a42c3
    parameters_practitionerId-3:
      in: query
      name: practitioner_id
      description: A comma-separated list of practitioner IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128c05a210879a60ac1ac,69c128bf5a210879a60ac1a8
      deprecated: true
    practitionerIds:
      in: query
      name: practitioner_ids
      description: A comma-separated list of practitioner IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128c05a210879a60ac1ac,69c128bf5a210879a60ac1a8
    shopCategoryIds:
      in: query
      name: shop_category_ids
      description: A comma-separated list of shop category ids to filter on (includes offering and voucher categories).
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128bf5a210879a60ac18f,69c128c05a210879a60ac231
    parameters_roomId-2:
      in: query
      name: room_id
      description: A comma-separated list of room IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      deprecated: true
    roomIds:
      in: query
      name: room_ids
      description: A comma-separated list of room IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128bf5a210879a60ac18f,69c128c05a210879a60ac231
    parameters_zoneId-2:
      in: query
      name: zone_id
      description: A comma-separated list of zone IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      deprecated: true
    zoneIds:
      in: query
      name: zone_ids
      description: A comma-separated list of zone IDs to filter on.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
      example: 69c128bf5a210879a60ac18f,69c128c05a210879a60ac231
    parameters_sort-2:
      in: query
      name: sort
      description: The field to order results by.
      schema:
        type: string
    sortOrder:
      in: query
      name: sort_order
      description: The direction to order results by.
      schema:
        type: string
        enum:
          - asc
          - desc
    parameters_siteId-11:
      in: query
      name: site_id
      description: Restrict the report to orders belonging to the given site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom:
      in: query
      name: revenue_date_from
      description: Filter to orders with revenues on or after this date.
      required: true
      schema:
        type: string
        format: date
      example: '2026-01-15'
    parameters_revenueDateTo:
      in: query
      name: revenue_date_to
      description: Filter to orders with revenues on or before this date.
      required: true
      schema:
        type: string
        format: date
      example: '2026-01-15'
    parameters_tableReservationTypeId:
      in: path
      name: tableReservationTypeId
      description: The ID of the table reservation type.
      required: true
      schema:
        type: string
        format: object-id
    optionId:
      in: path
      name: optionId
      description: The ID of the option.
      required: true
      schema:
        type: string
        format: object-id
    parameters_code:
      in: path
      name: code
      required: true
      schema:
        type: string
      description: The barcode to search for
    parameters_siteId-12:
      in: query
      name: site_id
      schema:
        type: string
        format: uuid
      description: The ID of the site to filter products on
    mediaId:
      in: path
      name: mediaId
      required: true
      description: The ID of the Media resource
      schema:
        type: string
        format: uuid
    parameters_siteId-13:
      in: query
      name: site_id
      description: Filter the list of `LedgerLinePosting`s by site
      schema:
        type: string
        format: uuid
    parameters_status-2:
      in: query
      name: status
      description: Filter the list of `LedgerLinePosting`s by status
      schema:
        type: string
        enum:
          - success
          - resolved
          - error
          - in_progress
          - not_started
    parameters_sort-3:
      in: query
      name: sort
      description: Sort the list by the given column name
      schema:
        type: string
        example: created_at
    sortDirectionQuery:
      in: query
      name: sort_direction
      required: false
      description: The direction to sort the results in.
      schema:
        type: string
        enum:
          - asc
          - desc
    createdAtFrom:
      in: query
      name: created_at_from
      description: Filter the list of `LedgerLinePosting`s by created at from. This will include the given date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    createdAtTo:
      in: query
      name: created_at_to
      description: Filter the list of `LedgerLinePosting`s by created at to. This will filter up to and including the given date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    succeededAtFrom:
      in: query
      name: succeeded_at_from
      description: Filter the list of `LedgerLinePosting`s by succeeded at from. This will include the given date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    succeededAtTo:
      in: query
      name: succeeded_at_to
      description: Filter the list of `LedgerLinePosting`s by succeeded at to. This will filter up to and including the given date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    ledgerLinePostingId:
      in: path
      name: ledgerLinePostingId
      description: The ID of the LedgerLinePosting
      required: true
      schema:
        type: string
        format: object-id
    practitionerRotaId:
      name: practitionerRotaId
      in: path
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the `PractitionerRota`.
    practitionerTagId:
      name: practitionerTagId
      in: path
      required: true
      description: The unique identifier of the `PractitionerTag`.
      schema:
        type: string
        format: object-id
    parameters_query-6:
      in: query
      name: query
      required: false
      schema:
        type: string
      description: Filter practitioners by their name
    parameters_zoneIds:
      name: zone_ids
      description: Filter practitioners by a comma separated list of `zone` ids they are linked to
      in: query
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8768
    parameters_practitionerId-4:
      name: practitionerId
      in: path
      required: true
      schema:
        type: string
      description: |
        Identifier of the practitioner. Practitioners are the staff
        members or therapists who deliver appointments; this ID is used
        to manage their rotas, availability, and assignment to bookings.
    appointmentRestrictionId:
      name: appointmentRestrictionId
      in: path
      required: true
      description: The unique identifier of the appointment restriction.
      schema:
        type: string
        format: object-id
    parameters_date-3:
      in: query
      name: date
      schema:
        type: string
        format: date
      description: Return only rules that overlap this calendar day (in the practitioner's timezone).
      example: '2026-06-01'
    parameters_dateTimeFrom:
      in: query
      name: date_time_from
      schema:
        type: string
        format: date-time
      description: Return only rules ending after this ISO 8601 timestamp.
      example: '2026-06-01T00:00:00+01:00'
    parameters_dateTimeTo:
      in: query
      name: date_time_to
      schema:
        type: string
        format: date-time
      description: Return only rules starting before this ISO 8601 timestamp.
      example: '2026-06-30T23:59:59+01:00'
    isAvailable:
      in: query
      name: is_available
      schema:
        type: boolean
      description: Filter by whether the rule opens (`true`) or blocks (`false`) bookings.
    customAvailabilityId:
      name: customAvailabilityId
      in: path
      required: true
      description: The unique identifier of the custom availability rule.
      schema:
        type: string
        format: object-id
    rotaId:
      name: rotaId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the PractitionerRota.
    roomTagId:
      name: roomTagId
      in: path
      required: true
      description: The unique identifier of the `RoomTag`.
      schema:
        type: string
        format: object-id
    parameters_zoneId-3:
      name: zoneId
      in: path
      required: true
      description: The unique identifier of the `Zone`.
      schema:
        type: string
        format: object-id
    country_code:
      in: query
      name: country_code
      description: An optional country code to filter tax configurations
      schema:
        type: string
    taxConfigurationId:
      in: path
      name: taxConfigurationId
      description: The ID of the tax configuration
      required: true
      schema:
        type: string
    parameters_siteId-14:
      in: query
      name: site_id
      schema:
        type: string
        format: uuid
      description: The ID of the site to filter visits by.
    basketIds:
      in: query
      name: basket_ids
      schema:
        type: array
        items:
          type: string
          format: mongo-id
      explode: false
      description: An array of basket IDs to generate visit-intake-forms for
    visitId:
      in: path
      name: visitId
      description: The ID of the visit
      required: true
      schema:
        type: string
        format: object-id
    guestId:
      in: path
      name: guestId
      description: The guest ID
      required: true
      schema:
        type: string
        format: object-id
    parameters_siteId-15:
      in: query
      name: site_id
      schema:
        type: string
        format: uuid
      description: Filter VisitTypes that belong to the given site ID
    visitTypeId:
      in: path
      name: visitTypeId
      schema:
        type: string
        format: object-id
      description: The unique identifier of the `VisitType`.
    webhookConfigId:
      in: path
      name: webhookConfigId
      schema:
        type: string
        format: object-id
      description: The unique identifier of the `WebhookConfig`.
    amountType:
      in: query
      name: amount_type
      description: Filter voucher types by their amount type.
      schema:
        type: string
        enum:
          - cash
          - discount_to_zero
    customisableAmount:
      in: query
      name: customisable_amount
      description: Filter voucher types by their customisable amount status.
      schema:
        type: boolean
    parameters_query-7:
      in: query
      name: query
      description: Filter voucher types by their name.
      schema:
        type: string
    parameters_voucherTypeId:
      name: voucherTypeId
      description: The ID of the `VoucherType`.
      in: path
      required: true
      schema:
        type: string
        format: object-id
    voucherDeliveryOptionId:
      in: path
      name: voucherDeliveryOptionId
      schema:
        type: string
        format: object-id
      description: The unique identifier for the voucher delivery option
    parameters_code-2:
      name: code
      in: path
      required: true
      description: |
        The redemption code, exactly as quoted by the customer. Codes are
        case-sensitive and may contain letters, digits, and dashes (e.g.
        `SUMMER2026-X9K2`).
      schema:
        type: string
        example: SUMMER2026-X9K2
    voucherId:
      name: voucherId
      in: path
      required: true
      description: The ID of the `Voucher` to operate on.
      schema:
        type: string
        format: object-id
        example: 65f0a1b2c3d4e5f6a7b8c9d0
    parameters_offeringId-2:
      name: offeringId
      in: path
      required: true
      description: |
        The ID of the offering to remove from the voucher's
        `valid_offerings` allowlist. For membership offerings, this is the
        composite ID exposed by the `getVoucher` response (of the form
        `{membership_type_id}_{membership_rate_id}_{duration}`).
      schema:
        type: string
        example: 65f0a1b2c3d4e5f6a7b8c9d4
    parameters_query-8:
      in: query
      name: query
      schema:
        type: string
      description: Filters customers with a similar name, email or phone number to the given value
      example: '@try.be'
    parameters_email:
      in: query
      name: email
      schema:
        type: string
        format: email
      description: Filter customers with the given email address
      example: hello@example.com
    organisation_id:
      in: query
      name: organisation_id
      schema:
        type: string
        format: uuid
      description: Filter customers that belong to the given organisation ID
    brand_id:
      in: query
      name: brand_id
      schema:
        type: string
        format: uuid
      description: Filter customers that belong to the given brand ID
    site_id:
      in: query
      name: site_id
      schema:
        type: string
        format: uuid
      description: Filter customers that belong to the given site ID
    membership_number:
      in: query
      name: membership_number
      schema:
        type: string
      description: Filter customers that have a membership with the given membership number
      example: '1234567890'
    name:
      in: query
      name: name
      schema:
        type: string
      description: Filter customers with a similar name to the given value
      example: Jane
    phone:
      in: query
      name: phone
      schema:
        type: string
      description: Filter customers with the given phone number
      example: 1234567890
    membership:
      in: query
      name: membership
      schema:
        type: string
      description: |
        Filter customers that have at least one membership of the given state.
        Set to "none" to filter customers that do not have any memberships,
        "any" to filter customers that have any memberships, and
        "needs_dd_mandate" for memberships awaiting a Direct Debit mandate or payment method.
    membership_created_at_from:
      in: query
      name: membership_created_at_from
      schema:
        type: string
      description: |
        Filters customers which have at least one membership that was created on or after the given date
    membership_created_at_to:
      in: query
      name: membership_created_at_to
      schema:
        type: string
      description: |
        Filters customers which have at least one membership that was created on or before the given date
    membership_type_id:
      in: query
      name: membership_type_id
      schema:
        type: string
      description: |
        Filters customers which have at least one membership of the given membership type ID
    membership_rate_id:
      in: query
      name: membership_rate_id
      schema:
        type: string
      description: |
        Filters customers which have at least one membership of the given membership rate ID
    marketing_opt_in:
      in: query
      name: marketing_opt_in
      schema:
        type: string
      description: |
        Filters customers who are opted into the given marketing preference ID.
        Alternatively, pass "any" to filter customers opted into any marketing
        preference, or "none" to filter customers not opted into any preferences.
    label_ids:
      in: query
      name: label_ids
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      description: |
        Filters customers which have the given CustomerLabel ids.
    created_at_from:
      in: query
      name: created_at_from
      schema:
        type: string
      description: Filters customers that were created on or after the given date.
    created_at_to:
      in: query
      name: created_at_to
      schema:
        type: string
      description: Filters customers that were created on or before the given date.
    id:
      in: query
      name: id
      schema:
        type: string
        items:
          type: string
          format: uuid
      explode: false
      description: Filters to just the customers with the given IDs.
    barcodeId:
      in: path
      name: barcodeId
      required: true
      description: The ID of the barcode
      schema:
        type: string
    parameters_organisationId:
      in: query
      name: organisation_id
      description: |
        Optional organisation filter. When provided, only marketing
        preferences belonging to the supplied organisation are returned;
        omit to list preferences across every organisation the caller
        has access to.
      required: false
      schema:
        type: string
        description: Filters marketing preferences that are associated with the given organisation ID
    marketingPreferenceId:
      in: path
      name: marketingPreferenceId
      description: The ID of the marketing preference
      required: true
      schema:
        type: string
        format: uuid
    customer_id:
      in: query
      name: customer_id
      description: Filter payment methods that belong to the given customer ID
      schema:
        type: string
        format: uuid
    parameters_type:
      in: query
      name: type
      description: Filter payment methods by type (e.g., card, direct_debit)
      schema:
        type: string
        enum:
          - card
          - direct_debit
    processor:
      in: query
      name: processor
      description: |
        Filter payment methods by the processor that issued them. Most
        integrators don't need this filter — payment-method handling is
        abstracted at the order-payment layer.
      schema:
        type: string
        enum:
          - stripe
          - adyen
          - manual
    parameters_status-3:
      in: query
      name: status
      description: Filter payment methods by status (e.g., active, revoked)
      schema:
        type: string
        enum:
          - pending
          - active
          - revoked
    membership_payment_method:
      in: query
      name: membership_payment_method
      description: Filter payment methods that are used for memberships
      schema:
        type: string
    for_barcode:
      in: query
      name: for_barcode
      description: Filter payment methods that are associated with barcodes (wearable devices)
      schema:
        type: boolean
        default: false
    parameters_siteId-16:
      name: siteId
      in: path
      description: The site ID
      required: true
      schema:
        type: string
        format: uuid
    deviceId:
      in: path
      name: deviceId
      description: The ID of the device
      required: true
      schema:
        type: string
        format: uuid
    parameters_membershipTypeId:
      in: path
      name: membershipTypeId
      description: The ID of the membership type
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-17:
      in: query
      name: site_id
      description: Filter inventory brands by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_query-9:
      in: query
      name: query
      description: |
        A search query to filter inventory brands by. This will search the brand name.
      required: false
      schema:
        type: string
    brandId:
      in: path
      name: brandId
      description: |
        Stable identifier for the `InventoryBrand`. Inventory brands
        group together suppliers, products and stock locations for a
        consistent merchandising experience across multiple sites that
        share the same retail catalogue.
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-18:
      in: query
      name: site_id
      description: Filter inventory categories by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_query-10:
      in: query
      name: query
      description: |
        A search query to filter inventory categories by. This will search the category name.
      required: false
      schema:
        type: string
    parameters_categoryId-4:
      in: path
      name: categoryId
      description: The ID of the `InventoryCategory`
      required: true
      schema:
        type: string
        format: uuid
    ids:
      in: query
      name: ids
      description: |
        A comma-separated list of supplier IDs to retrieve.
      required: false
      schema:
        type: string
        format: uuid
    parameters_siteId-19:
      in: query
      name: site_id
      description: Filter suppliers by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_query-11:
      in: query
      name: query
      description: |
        A search query to filter suppliers by. This will search the supplier name.
      required: false
      schema:
        type: string
    supplierId:
      in: path
      name: supplierId
      description: The ID of the `Supplier`
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-20:
      in: query
      name: site_id
      required: true
      description: Filter inventory products by site.
      schema:
        type: string
        format: uuid
    supplierIds:
      in: query
      name: supplier_ids
      required: false
      description: |
        A comma-separated list of supplier IDs to retrieve inventory products for.
      schema:
        type: string
        format: uuid
    parameters_categoryIds:
      in: query
      name: category_ids
      required: false
      description: |
        A comma-separated list of category IDs to retrieve inventory products for.
      schema:
        type: string
        format: uuid
    parameters_brandIds:
      in: query
      name: brand_ids
      required: false
      description: |
        A comma-separated list of brand IDs to retrieve inventory products for.
      schema:
        type: string
        format: uuid
    parameters_query-12:
      in: query
      name: query
      required: false
      description: |
        A search query to filter inventory products by. This will search the product name.
      schema:
        type: string
    parameters_productId:
      in: path
      name: productId
      description: The ID of the `InventoryProduct`
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-21:
      in: query
      name: site_id
      required: true
      description: Filter stock on hand by site.
      schema:
        type: string
        format: uuid
    purchaseOrderNumber:
      in: query
      name: purchase_order_number
      required: false
      description: |
        A search query to filter inventory orders by the purchase order number.
      schema:
        type: string
    orderId:
      in: path
      name: orderId
      description: The ID of the `InventoryOrder`
      required: true
      schema:
        type: string
        format: uuid
    parameters_brandIds-2:
      in: query
      name: brand_ids
      required: false
      description: |
        A comma-separated list of brand IDs to retrieve inventory order items for.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_categoryIds-2:
      in: query
      name: category_ids
      required: false
      description: |
        A comma-separated list of category IDs to retrieve inventory order items for.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    orderItemId:
      in: path
      name: orderItemId
      description: The ID of the `InventoryOrderItem`
      required: true
      schema:
        type: string
        format: uuid
    parameters_orderId:
      in: path
      name: orderId
      description: |
        Identifier of the inventory order whose queued job status is being
        fetched. Queue endpoints return progress for async operations
        (sending, receiving, exporting); poll until the job completes.
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-22:
      in: query
      name: site_id
      description: Filter the `InventoryOrder` by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-23:
      in: query
      name: site_id
      required: true
      description: Filter stocktakes by site.
      schema:
        type: string
        format: uuid
    stockTakeId:
      in: path
      name: stockTakeId
      description: |
        Identifier of the stocktake. Returned from `createStockTake`; use it
        to read the stocktake, list or update its items, post the final
        counts, or poll the async queue for export status.
      required: true
      schema:
        type: string
        format: uuid
    parameters_brandIds-3:
      in: query
      name: brand_ids
      required: false
      description: |
        A comma-separated list of brand IDs to retrieve stocktake items for.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_categoryIds-3:
      in: query
      name: category_ids
      required: false
      description: |
        A comma-separated list of category IDs to retrieve stocktake items for.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_supplierIds:
      in: query
      name: supplier_ids
      required: false
      description: |
        A comma-separated list of supplier IDs to retrieve stocktake items for.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_query-13:
      in: query
      name: query
      required: false
      description: |
        A search query to filter stocktake items by. This will search the item name.
      schema:
        type: string
        format: uuid
    parameters_status-4:
      in: query
      name: status
      required: false
      description: |
        The status to filter the stocktake items by.
      schema:
        type: string
        enum:
          - all
          - uncounted
          - counted
    stockTakeItemId:
      in: path
      name: stockTakeItemId
      description: The ID of the `StockTakeItem`
      required: true
      schema:
        type: string
        format: uuid
    parameters_stockTakeId:
      in: path
      name: stockTakeId
      description: |
        Identifier of the stocktake whose queued export job status is being
        fetched. Posting a stocktake kicks off an async job; poll this
        endpoint until the job reports as complete.
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-24:
      in: query
      name: site_id
      description: Filter the `StockTake` by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_date-4:
      in: query
      name: date
      required: true
      description: |
        The date to filter stock on hand by.
      schema:
        type: string
        format: date
    parameters_brandIds-4:
      in: query
      name: brand_ids
      required: false
      description: |
        A comma-separated list of brand IDs to filter stock on hand by.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_categoryIds-4:
      in: query
      name: category_ids
      required: false
      description: |
        A comma-separated list of category IDs to filter stock on hand by.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_supplierIds-2:
      in: query
      name: supplier_ids
      required: false
      description: |
        A comma-separated list of supplier IDs to filter stock on hand by.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_siteId-25:
      in: query
      name: site_id
      required: true
      description: Filter stock adjustments by site.
      schema:
        type: string
        format: uuid
    parameters_dateFrom-2:
      in: query
      name: date_from
      required: true
      description: |
        Filter the list of stock adjustments by the date the adjustment was made.
        The adjustment must have been made on or after this date.
      schema:
        type: string
        format: date
    parameters_dateTo-2:
      in: query
      name: date_to
      required: true
      description: |
        Filter the list of stock adjustments by the date the adjustment was made.
        The adjustment must have been made on or before this date.
      schema:
        type: string
        format: date
    parameters_brandIds-5:
      in: query
      name: brand_ids
      required: false
      description: |
        Filter the list of stock adjustments by a comma-separated list of brand IDs associated with the inventory products.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_categoryIds-5:
      in: query
      name: category_ids
      required: false
      description: |
        Filter the list of stock adjustments by a comma-separated list of category IDs associated with the inventory products.
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    appointmentEnquiryId:
      in: path
      name: appointmentEnquiryId
      description: The ID of the appointment enquiry.
      schema:
        type: string
        format: mongo-id
    redemptionType:
      in: query
      name: redemption_type
      required: false
      schema:
        type: string
        enum:
          - manual
          - programmatic
      description: |
        Filter coupons by redemption type. When not provided, defaults to `manual`.
      example: programmatic
    couponId:
      in: path
      name: couponId
      required: true
      description: |
        Identifier of the coupon record. Returned from `listCoupons` and
        `createCoupon`; used to update the coupon, manage its offering
        discounts, or issue redemption codes.
      schema:
        type: string
        format: object-id
    parameters_couponCodeId:
      name: couponCodeId
      in: path
      required: true
      description: The unique identifier of the `CouponCode`.
      schema:
        type: string
        format: object-id
    offeringDiscountId:
      in: path
      name: offeringDiscountId
      description: |
        Identifier of the offering-discount rule attached to a coupon.
        Offering discounts link a coupon to a specific offering and define
        the discount amount/percentage to apply when the coupon is
        redeemed against that offering.
      required: true
      schema:
        type: string
        format: object-id
    parameters_code-3:
      in: path
      name: code
      required: true
      description: The coupon code
      schema:
        type: string
    bookingDate:
      in: query
      name: booking_date
      required: true
      description: The booking date to calculate usage stats for (YYYY-MM-DD or ISO8601 datetime)
      schema:
        type: string
    parameters_offeringId-3:
      in: query
      name: offering_id
      required: false
      description: When provided, returns null data if the coupon does not apply to this offering
      schema:
        type: string
    receiptId:
      in: path
      name: receiptId
      description: The ID of the fiscal receipt
      required: true
      schema:
        type: string
        format: object-id
    actionId:
      in: path
      name: actionId
      description: The ID of the fiscalisation action.
      required: true
      schema:
        type: string
        format: object-id
    eventId:
      name: event
      in: path
      required: true
      description: The ID of the fiscalisation journal event.
      schema:
        type: string
        format: mongo-id
    parameters_query-14:
      in: query
      name: query
      schema:
        type: string
      description: The query to filter orders on.
    customerId:
      in: query
      name: customer_id
      schema:
        type: string
        format: uuid
      description: The customer ID to filter orders on.
      example: Jane
    parameters_status-5:
      in: query
      name: status
      schema:
        type: string
      description: The status to filter orders on.
      example: settled
    labels:
      in: query
      name: labels
      schema:
        type: string
        items:
          type: string
      explode: false
      description: The labels to filter orders on.
      example: settled
    itemOfferingId:
      in: query
      name: item_offering_id
      schema:
        type: string
        items:
          type: string
          format: object-id
      explode: false
      description: A comma separated string of offering ids to fetch orders for
    itemOfferingType:
      in: query
      name: item_offering_type
      schema:
        $ref: '#/components/schemas/OfferingType'
      description: Filter orders by the type of offering for their items.
      example: course
    submittedById:
      in: query
      name: submitted_by_id
      schema:
        type: string
        items:
          type: string
          format: object-id
      explode: false
      description: A comma separated string of user ids to fetch orders for
      example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8767
    parameters_revenueDateFrom-2:
      in: query
      name: revenue_date_from
      schema:
        type: string
        format: date
      description: Filter on orders with a revenue date on or after this date.
      example: '2019-01-15'
    parameters_revenueDateTo-2:
      in: query
      name: revenue_date_to
      schema:
        type: string
        format: date
      description: Filter on orders with a revenue date on or before this date.
    itemDate:
      in: query
      name: item_date
      schema:
        type: string
        format: date
      description: Filter on orders with an items on this date.
    parameters_itemDateFrom:
      in: query
      name: item_date_from
      schema:
        type: string
        format: date-time
      description: Filter on orders with an item date on or after this date.
    parameters_itemDateTo:
      in: query
      name: item_date_to
      schema:
        type: string
        format: date-time
      description: Filter on orders with an item date on or before this date.
    itemStatus:
      in: query
      name: item_status
      schema:
        type: string
        items:
          type: string
      explode: false
      description: Filter on orders with an item status of one of these comma-separated values.
      example: confirmed
    submittedAtFrom:
      in: query
      name: submitted_at_from
      schema:
        type: string
        format: date-time
      description: Filter on orders with a submitted date on or after this time.
    submittedAtTo:
      in: query
      name: submitted_at_to
      schema:
        type: string
        format: date-time
      description: Filter on orders with a submitted date before this date.
    updatedAtFrom:
      in: query
      name: updated_at_from
      schema:
        type: string
        format: date-time
      description: Filter on orders with a updated date on or after this date.
    updatedAtTo:
      in: query
      name: updated_at_to
      schema:
        type: string
        format: date-time
      description: Filter on orders with a updated date before this date.
    isMembership:
      in: query
      name: is_membership
      schema:
        type: boolean
      description: Filter on orders that contain a membership purchase
    hasOutstandingBalance:
      in: query
      name: has_outstanding_balance
      schema:
        type: boolean
      description: Filters on orders that have an outstanding balance
    salesChannel:
      in: query
      name: sales_channel
      schema:
        type: string
        format: object-id
      description: Filter on orders that have the given sales channel ID
    externalId:
      in: query
      name: external_id
      schema:
        type: string
      description: Filter on an external ID, in the format `{key}:{value}`
      example: pms_id:id_123
    genericItemsArray:
      in: query
      name: generic_items_array
      schema:
        type: boolean
      description: Pass `true` to return a single 'items' array rather than separate arrays for each item type
    parameters_orderId-2:
      in: path
      name: orderId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the order
    parameters_paymentId-2:
      in: path
      name: paymentId
      description: The ID of the payment.
      required: true
      schema:
        type: string
        format: object-id
    discountId:
      in: path
      name: discountId
      description: The ID of the order discount
      required: true
      schema:
        type: string
        format: uuid
    emailId:
      in: path
      name: emailId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the email message.
    parameters_guestId:
      in: path
      name: guestId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the guest on the order.
    parameters_itemId:
      in: path
      name: itemId
      description: The ID of the order item
      required: true
      schema:
        type: string
        format: uuid
    parameters_orderId-3:
      in: path
      name: orderId
      description: The ID of the order
      required: true
      schema:
        type: string
        format: uuid
    parameters_discountId:
      in: path
      name: discountId
      description: The ID of the order item discount
      required: true
      schema:
        type: string
        format: uuid
    labelId:
      in: path
      name: labelId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the label to add to or remove from the order.
    noteId:
      in: path
      name: noteId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the order note.
    discountTypeId:
      in: path
      name: discountTypeId
      description: The ID of the discount type
      required: true
      schema:
        type: string
        format: uuid
    tipId:
      name: tipId
      in: path
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the tip to remove
    smsId:
      in: path
      name: smsId
      description: The ID of the SMS Fragment
      required: true
      schema:
        type: string
        format: object-id
    parameters_customerCreditId:
      in: path
      name: customerCreditId
      required: true
      schema:
        type: string
      description: The ID of the customer credit applied to the order.
    payoutId:
      in: path
      name: payoutId
      description: |
        Identifier of the payout. Payouts represent transfers from
        Trybe-managed payment processing into the merchant's bank
        account; this ID lets you read the payout breakdown or retry a
        failed transfer.
      required: true
      schema:
        type: string
        format: object-id
    integrationConfigId:
      in: path
      name: integrationConfigId
      description: |
        Identifier of the integration configuration. Returned from
        `listIntegrationConfigs`; used to enable, disable, link to a site,
        or query its outage history.
      required: true
      schema:
        type: string
        format: object-id
    parameters_organisationId-2:
      in: path
      name: organisationId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        Identifier of the organisation. Organisations group sites together
        under a single billing/admin entity; the caller's API key must
        have access to the named organisation.
    voucherApplicable:
      in: query
      name: voucher_applicable
      required: false
      description: Only return voucher categories.
      schema:
        type: boolean
    parameters_categoryId-5:
      in: path
      name: categoryId
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the `Category`.
    customPaymentTypeId:
      in: path
      name: customPaymentTypeId
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the `CustomPaymentType`.
    from:
      in: query
      name: from
      required: false
      schema:
        type: string
        format: date
      description: Retrieve `DataSet`s after this value.
    limit:
      in: query
      name: limit
      required: false
      schema:
        type: integer
      description: The number of `DataSet`s to retrieve.
    dateSetId:
      in: path
      name: dateSetId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the `DateSet`.
    recurrenceEndAfter:
      in: query
      name: recurrence_end_after
      required: false
      schema:
        type: string
        format: date
        example: '2025-11-10'
      description: Retrieve `SessionRecurrenceGroup`s where the end date is after this value.
    recurrenceEndBefore:
      in: query
      name: recurrence_end_before
      required: false
      schema:
        type: string
        format: date
        example: '2025-11-10'
      description: Retrieve `SessionRecurrenceGroup`s where the end date is before this value.
    sessionTypeId:
      name: session_type_id
      in: query
      required: false
      style: form
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
      description: A comma separated list of `SessionType` ids.
    recurrenceGroupId:
      name: recurrenceGroupId
      in: path
      description: |
        Identifier of the session recurrence group. Recurrence groups
        represent a series of recurring class or session instances; this
        ID lets you update the series (e.g. cancel future occurrences,
        change capacity) or delete it outright.
      required: true
      schema:
        type: string
        format: object-id
    schedulingIssueId:
      name: schedulingIssueId
      in: path
      required: true
      description: The unique identifier of the `SchedulingIssue`.
      schema:
        type: string
        format: object-id
    cancelled:
      name: cancelled
      in: query
      required: false
      description: Whether to exclusively return cancelled `Session`s.
      schema:
        type: boolean
    parameters_id:
      name: id
      in: query
      required: false
      description: A comma separated list of `Session` ids to search for.
      schema:
        type: string
    includeBookings:
      name: include_bookings
      in: query
      required: false
      description: Whether to include associated `Booking`s.
      schema:
        type: boolean
    includeCancelled:
      name: include_cancelled
      in: query
      required: false
      description: Whether to include cancelled `Session`s.
      schema:
        type: boolean
    parameters_practitionerId-5:
      name: practitioner_id
      in: query
      required: false
      description: A comma separated list of `Practitioner` ids.
      schema:
        type: string
    parameters_recurrenceGroupId:
      name: recurrence_group_id
      in: query
      required: false
      description: A comma separated list of `SessionRecurrenceGroup` ids.
      schema:
        type: string
    parameters_roomId-3:
      name: room_id
      in: query
      required: false
      description: A comma separated list of `Room` ids.
      schema:
        type: string
    parameters_sessionTypeId:
      name: session_type_id
      in: query
      required: false
      description: A comma separated list of `SessionType` ids.
      schema:
        type: string
    parameters_zoneId-4:
      name: zone_id
      in: query
      required: false
      description: A comma separated list of `Zone` ids.
      schema:
        type: string
    startTimeFrom:
      name: start_time_from
      in: query
      required: false
      description: Filter results by when they start.
      schema:
        type: string
        format: date-time
        example: '2000-01-01T17:00:00+01:00'
    startTimeTo:
      name: start_time_to
      in: query
      required: false
      description: Filter results by when they end.
      schema:
        type: string
        format: date-time
        example: '2000-01-01T20:00:00+01:00'
    parameters_includeBookings:
      name: include_bookings
      in: query
      required: false
      description: Whether to include associated `Booking`s.
      schema:
        type: boolean
        default: false
    sessionId:
      name: sessionId
      in: path
      required: true
      description: The `Session` id.
      schema:
        type: string
        format: object-id
    parameters_query-15:
      name: query
      in: query
      description: |
        A search query to filter session types by. This will search the name of the session type.
      required: false
      schema:
        type: string
    include_recurrence_groups:
      name: include_recurrence_groups
      in: query
      description: Whether to include the `SessionRecurrenceGroup` relations.
      required: false
      schema:
        type: boolean
        default: true
    parameters_sessionTypeId-2:
      name: sessionTypeId
      in: path
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the session type
    includePriceRules:
      name: include_price_rules
      in: query
      required: false
      description: Whether or not to copy the associated `PriceRule`s.
      schema:
        type: boolean
    includeRecurrenceGroups:
      name: include_recurrence_groups
      in: query
      required: false
      description: Whether or not to copy the associated `RecurrenceGroup`s.
      schema:
        type: boolean
    newSiteDetailsId:
      in: path
      name: newSiteDetailsId
      required: true
      description: The ID of the new site details record
      schema:
        type: string
        format: object-id
    parameters_voucherApplicable:
      name: voucher_applicable
      in: query
      description: |
        whether to include voucher applicable categories in the response.
      required: false
      schema:
        type: boolean
    openingHoursOverrideId:
      in: path
      name: openingHoursOverrideId
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the opening hour override.
    revenueCentreId:
      in: path
      name: revenueCentreId
      description: The ID of the revenue centre
      required: true
      schema:
        type: string
    parameters_integrationConfigId:
      in: query
      name: integration_config_id
      description: The ID of the integration config.
      required: false
      schema:
        type: string
        format: object-id
    exportId:
      in: path
      name: exportId
      description: The ID of the Fiskaly export.
      required: true
      schema:
        type: string
        format: uuid
    rateCode:
      in: path
      name: rateCode
      required: true
      description: The rate code to remove.
      schema:
        type: string
    parameters_integrationConfigId-2:
      in: path
      name: integrationConfigId
      description: The ID of the integration config.
      required: true
      schema:
        type: string
        format: object-id
    parameters_siteId-26:
      in: path
      name: siteId
      description: |
        Identifier of the site whose SMS settings are being read or
        updated. SMS settings (sender names, default templates, Twilio
        bindings) are scoped per site so each location can configure its
        own customer-comms behaviour.
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-27:
      in: path
      name: siteId
      description: |
        Identifier of the site whose Twilio provisioning request is being
        created or read. Provisioning is async; once started, poll the
        provisioning record to know when the site's SMS sender is ready.
      required: true
      schema:
        type: string
        format: uuid
    provisionId:
      in: path
      name: provisionId
      description: The ID of the Twilio number provision.
      required: true
      schema:
        type: string
    parameters_siteId-28:
      in: path
      name: siteId
      description: |
        Identifier of the site whose supported communication locales are
        being read or updated. The locales control which translations are
        selectable when authoring email/SMS templates and which locales
        customers may pick from at checkout.
      required: true
      schema:
        type: string
        format: uuid
    parameters_sessionId:
      in: query
      name: session_id
      required: true
      schema:
        type: string
      description: |
        The Stripe Checkout session ID supplied by Stripe when redirecting
        back from the setup flow. The placeholder `{CHECKOUT_SESSION_ID}`
        is replaced by Stripe with the real ID.
      example: cs_test_a1b2c3d4e5f6
    signature:
      in: query
      name: signature
      required: true
      schema:
        type: string
      description: |
        The Laravel signed-URL signature that proves the redirect
        originated from `getSiteBillingSetupUrl`. Stripe forwards this
        value verbatim on completion.
    logoMediaId:
      in: query
      name: logo_media_id
      required: false
      schema:
        type: string
        format: uuid
        nullable: true
      description: |
        Optional ID of an uploaded `Media` asset to use as the email
        logo. When provided, the rendered preview will show the asset's
        public URL. Pass `null` (or omit) to render with no logo.
      example: 5f8d944e79c9f341846e807a
    accentColour:
      in: query
      name: accent_colour
      required: true
      schema:
        type: string
      description: Brand accent colour as a 3- or 6-digit hex code (e.g. `#1F7AE0`).
      example: '#1F7AE0'
    backgroundColour:
      in: query
      name: background_colour
      required: true
      schema:
        type: string
      description: Email background colour as a hex code.
      example: '#FFFFFF'
    textColour:
      in: query
      name: text_colour
      required: true
      schema:
        type: string
      description: Primary body text colour as a hex code.
      example: '#1A1A1A'
    successColour:
      in: query
      name: success_colour
      required: true
      schema:
        type: string
      description: Colour used for success states (e.g. confirmation badges).
      example: '#1FA971'
    successContrastColour:
      in: query
      name: success_contrast_colour
      required: true
      schema:
        type: string
      description: Foreground colour shown on top of `success_colour`.
      example: '#FFFFFF'
    infoColour:
      in: query
      name: info_colour
      required: true
      schema:
        type: string
      description: Colour used for informational states.
      example: '#1F7AE0'
    infoContrastColour:
      in: query
      name: info_contrast_colour
      required: true
      schema:
        type: string
      description: Foreground colour shown on top of `info_colour`.
      example: '#FFFFFF'
    dangerColour:
      in: query
      name: danger_colour
      required: true
      schema:
        type: string
      description: Colour used for destructive states.
      example: '#D14343'
    dangerContrastColour:
      in: query
      name: danger_contrast_colour
      required: true
      schema:
        type: string
      description: Foreground colour shown on top of `danger_colour`.
      example: '#FFFFFF'
    greetingType:
      in: query
      name: greeting_type
      required: true
      schema:
        type: string
      description: |
        The salutation style to use at the top of customer emails. See
        `BrandEmailConfig::GREETING_TYPES` on the platform — typical
        values are `formal`, `informal`, or `none`.
      example: informal
    signOffType:
      in: query
      name: sign_off_type
      required: true
      schema:
        type: string
      description: |
        The sign-off style to use at the bottom of customer emails.
        Typical values are `formal`, `informal`, or `none`.
      example: informal
    basketConfirmedEmailMessage:
      in: query
      name: basket_confirmed_email_message
      required: false
      schema:
        type: string
      description: |
        Optional custom message body, in HTML, that will appear in the
        previewed basket-confirmation email. Tags outside Trybe's
        allow-list are stripped.
    kioskConfigId:
      in: path
      name: kioskConfigId
      description: The ID of the `KioskConfig`
      required: true
      schema:
        type: string
        format: object-id
    kioskDeviceId:
      in: path
      name: kioskDeviceId
      description: The ID of the `KioskDevice`
      required: true
      schema:
        type: string
        format: object-id
    kioskBufferTimeRuleId:
      in: path
      name: kioskBufferTimeRuleId
      description: The ID of the `KioskBufferTimeRule`
      required: true
      schema:
        type: string
        format: mongo-id
    kioskInstructionId:
      in: path
      name: kioskInstructionId
      description: The ID of the `KioskInstruction`
      required: true
      schema:
        type: string
        format: object-id
    parameters_siteId-29:
      in: query
      name: site_id
      description: |
        Identifier of the site whose message fragments should be returned.
        Message fragments are scoped per site so each location can author
        its own transactional email copy. The caller's API key must have
        access to this site.
      required: true
      schema:
        type: string
        format: uuid
    offering_id:
      name: offering_id
      in: query
      description: |
        When provided, restricts the returned message fragments to those
        that apply to the given offering (appointment type, session type,
        package etc.). The response is additionally sorted by
        `message_type` then `priority` to mirror the order fragments are
        rendered in the email. Omit to list every fragment at the site,
        sorted by `name`.
      required: false
      schema:
        type: string
        format: mongo-id
    messageFragmentId:
      in: path
      name: messageFragmentId
      description: The ID of the `MessageFragment`.
      required: true
      schema:
        type: string
        format: mongo-id
    parameters_offeringId-4:
      in: path
      name: offeringId
      description: |
        The ID of the offering to detach from the message fragment.
        Matches the `offering_id` field of an entry in the fragment's
        `offerings` list.
      required: true
      schema:
        type: string
        format: mongo-id
    parameters_siteId-30:
      in: query
      name: site_id
      description: |
        Identifier of the site whose SMS fragments should be returned.
        SMS fragments are scoped per site so each location can author its
        own SMS templates. The caller's API key must have access to this
        site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_offering_id:
      name: offering_id
      in: query
      description: |
        When provided, restricts the returned SMS fragments to those that
        apply to the given offering (treatment, class, course etc.). Omit
        to list SMS fragments across all offerings at the site.
      required: false
      schema:
        type: string
        format: uuid
    smsFragmentId:
      in: path
      name: smsFragmentId
      description: The ID of the `SmsFragment`
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-31:
      in: query
      name: site_id
      description: Filter the list of enquiries by site
      schema:
        type: string
        format: uuid
    parameters_status-6:
      in: query
      name: status
      description: Show enquiries of this status.
      schema:
        type: string
        enum:
          - received
          - confirmed
          - cancelled
    canConfirm:
      in: query
      name: can_confirm
      description: Filter the list of enquiries by whether they are currently able to be confirmed.
      schema:
        type: string
        format: boolean
    receivedFrom:
      in: query
      name: received_from
      description: Include enquiries where the date the enquiry was received is on or after this date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    receivedTo:
      in: query
      name: received_to
      description: Include enquiries where the date the enquiry was received is on or before this date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    parameters_appointmentTypeId-2:
      in: query
      name: appointment_type_id
      description: Show enquiries for this appointment type.
      schema:
        type: string
        format: object-id
    parameters_sortOrder:
      in: query
      name: sort_order
      description: The direction to order results by.
      required: false
      schema:
        type: string
        enum:
          - asc
          - desc
    parameters_siteId-32:
      in: query
      name: site_id
      description: Filter the list of `ClientAssociatedBarcode`s by site
      required: true
      schema:
        type: string
        format: uuid
    parameters_createdAtFrom:
      in: query
      name: created_at_from
      description: Filter the list of `ClientAssociatedBarcode`s by created date (ISO 8601 format)
      schema:
        type: string
        format: date-time
    parameters_createdAtTo:
      in: query
      name: created_at_to
      description: Filter the list of `ClientAssociatedBarcode`s by created date (ISO 8601 format)
      schema:
        type: string
        format: date-time
    expiresAtFrom:
      in: query
      name: expires_at_from
      description: Filter the list of `ClientAssociatedBarcode`s by expiry date (ISO 8601 format)
      schema:
        type: string
        format: date-time
    expiresAtTo:
      in: query
      name: expires_at_to
      description: Filter the list of `ClientAssociatedBarcode`s by expiry date (ISO 8601 format)
      schema:
        type: string
        format: date-time
    hasOrder:
      in: query
      name: has_order
      description: Filter the list of `ClientAssociatedBarcode`s by whether they have an associated order
      schema:
        type: boolean
    hasPaymentMethod:
      in: query
      name: has_payment_method
      description: Filter the list of `ClientAssociatedBarcode`s by whether they have an associated payment
      schema:
        type: boolean
    parameters_source:
      in: query
      name: source
      description: Filter the list of `ClientAssociatedBarcode`s by source
      schema:
        type: string
        example: kiosk
    parameters_date-5:
      in: query
      name: date
      description: The date to generate the itinerary for
      schema:
        type: string
        format: date
        example: '2023-05-05'
    parameters_siteId-33:
      in: query
      name: site_id
      schema:
        type: string
        format: uuid
      description: The ID of the site to generate the itinerary for
      example: 00000000-0000-0000-0000-000000000000
    parameters_siteId-34:
      in: query
      name: site_id
      description: Filter the list of `LedgerLine`s by site
      schema:
        type: string
        format: uuid
    ledgerDateFrom:
      in: query
      name: ledger_date_from
      description: Filter the list of `LedgerLine`s by ledger date from. This will include the given date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    ledgerDateTo:
      in: query
      name: ledger_date_to
      description: Filter the list of `LedgerLine`s by ledger date to. This will include the given date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    parameters_type-2:
      in: query
      name: type
      description: Show `LedgerLine`s of this type.
      schema:
        type: string
        example: revenue
        enum:
          - revenue
          - charge
    revenueCentre:
      in: query
      name: revenue_centre
      description: Filter the list of `LedgerLine`s by the revenue centre.
      schema:
        type: string
        example: spa_retail
    paymentProcessor:
      in: query
      name: payment_processor
      description: Filter the list of `LedgerLine`s by the payment processor.
      schema:
        type: string
        example: manual
    paymentProcessorTypeId:
      in: query
      name: payment_processor_type_id
      description: Filter the list of `LedgerLine`s by the payment processor type ID.
      schema:
        type: string
        example: 12345678
    parameters_voucherCodeId-2:
      in: query
      name: voucher_code_id
      description: Show `LedgerLine`s for this voucher code.
      schema:
        type: string
        format: object-id
    parameters_siteId-35:
      in: query
      name: site_id
      description: Filter the list of payouts by site.
      schema:
        type: string
        format: uuid
    parameters_status-7:
      in: query
      name: status
      description: Filter for payouts with a specific status.
      schema:
        type: string
        enum:
          - not_started
          - processing
          - processed
          - failed
    PractitionerOccupancyDateTimeFrom:
      name: date_time_from
      in: query
      required: true
      description: |
        The start of the reporting period as an ISO 8601 date-time string (e.g. `2024-01-01T00:00:00+00:00`). The range between `date_time_from` and `date_time_to` must not exceed 60 days.
      schema:
        type: string
        format: date-time
        example: '2024-01-01T00:00:00+00:00'
    PractitionerOccupancyDateTimeTo:
      name: date_time_to
      in: query
      required: true
      description: |
        The end of the reporting period as an ISO 8601 date-time string (e.g. `2024-01-31T23:59:59+00:00`). Must be after `date_time_from`. The range between `date_time_from` and `date_time_to` must not exceed 60 days.
      schema:
        type: string
        format: date-time
        example: '2024-01-31T23:59:59+00:00'
    PractitionerOccupancyPractitionerIds:
      name: practitioner_ids
      in: query
      required: false
      description: |
        A comma-separated string of practitioner IDs to filter the report to specific practitioners.
      schema:
        type: string
        example: 5dcb56d0-59fe-4581-83e1-a7b7c2d3e4f5,6eca67e1-6aff-5692-94f2-b8c8d3e4f5a6
    PractitionerOccupancySiteId:
      name: site_id
      in: query
      required: false
      description: The site ID to scope the report to.
      schema:
        type: string
        format: uuid
        example: 5dcb56d0-59fe-4581-83e1-a7b7c2d3e4f5
    PractitionerOccupancyByDateDateTimeFrom:
      name: date_time_from
      in: query
      required: false
      description: |
        The start of the reporting period as an ISO 8601 date-time string (e.g. `2024-01-01T00:00:00+00:00`). Required if `date_from` is not provided. The range between `date_time_from` and `date_time_to` must not exceed 60 days.
      schema:
        type: string
        format: date-time
        example: '2024-01-01T00:00:00+00:00'
    PractitionerOccupancyByDateDateTimeTo:
      name: date_time_to
      in: query
      required: false
      description: |
        The end of the reporting period as an ISO 8601 date-time string (e.g. `2024-01-31T23:59:59+00:00`). Must be after `date_time_from`. Required if `date_to` is not provided. The range between `date_time_from` and `date_time_to` must not exceed 60 days.
      schema:
        type: string
        format: date-time
        example: '2024-01-31T23:59:59+00:00'
    PractitionerOccupancyByDatePractitionerIds:
      name: practitioner_ids
      in: query
      required: false
      description: |
        A comma-separated string of practitioner IDs to filter the report to specific practitioners.
      schema:
        type: string
        example: 5dcb56d0-59fe-4581-83e1-a7b7c2d3e4f5,6eca67e1-6aff-5692-94f2-b8c8d3e4f5a6
    PractitionerOccupancyByDateSiteId:
      name: site_id
      in: query
      required: false
      description: The site ID to scope the report to.
      schema:
        type: string
        format: uuid
        example: 5dcb56d0-59fe-4581-83e1-a7b7c2d3e4f5
    PractitionerOccupancyByDateZoneId:
      name: zone_id
      in: query
      required: false
      description: A comma-separated string of zone IDs to filter by.
      schema:
        type: string
        nullable: true
        example: 5e932c0901d210625e3a8766,5e932c0901d210625e3a8768
    parameters_siteId-36:
      in: query
      name: site_id
      description: Filter the summary list of used promo codes by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-3:
      in: query
      name: revenue_date_from
      description: |
        Filter the summary list of used promo codes by revenue date of the order.
        The promo code must have been used on orders with bookings on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-01'
    parameters_revenueDateTo-3:
      in: query
      name: revenue_date_to
      description: |
        Filter the summary list of used promo codes by revenue date of the order.
        The promo code must have been used on orders with bookings on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-31'
    parameters_submittedAtFrom:
      in: query
      name: submitted_at_from
      description: |
        Filter the summary list of used promo codes by submitted date of the order.
        The promo code must have been used on orders submitted on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-31-01'
    parameters_submittedAtTo:
      in: query
      name: submitted_at_to
      description: |
        Filter the summary list of used promo codes by submitted date of the order.
        The promo code must have been used on orders submitted on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-31-10'
    parameters_siteId-37:
      in: query
      name: site_id
      description: Filter the breakdown list of used promo codes by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-4:
      in: query
      name: revenue_date_from
      description: |
        Filter the breakdown list of used promo codes by revenue date of the order.
        The promo code must have been used on orders with bookings on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-01'
    parameters_revenueDateTo-4:
      in: query
      name: revenue_date_to
      description: |
        Filter the breakdown list of used promo codes by revenue date of the order.
        The promo code must have been used on orders with bookings on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-31'
    parameters_submittedAtFrom-2:
      in: query
      name: submitted_at_from
      description: |
        Filter the breakdown list of used promo codes by submitted date of the order.
        The promo code must have been used on orders submitted on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-31-01'
    parameters_submittedAtTo-2:
      in: query
      name: submitted_at_to
      description: |
        Filter the breakdown list of used promo codes by submitted date of the order.
        The promo code must have been used on orders submitted on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-31-10'
    appliedBy:
      in: query
      name: applied_by
      description: |
        Filter the breakdown list of used promo codes by the user who applied the promo code.
        This can be either 'Customer' or a member of staff.
      required: false
      schema:
        type: string
        format: uuid
    parameters_siteId-38:
      in: query
      name: site_id
      description: Filter the summary list of used discount types by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-5:
      in: query
      name: revenue_date_from
      description: |
        Filter the summary list of used discount types by revenue date of the order.
        The discount type must have been used on orders with bookings on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-01'
    parameters_revenueDateTo-5:
      in: query
      name: revenue_date_to
      description: |
        Filter the summary list of used discount types by revenue date of the order.
        The discount type must have been used on orders with bookings on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-31'
    parameters_submittedAtFrom-3:
      in: query
      name: submitted_at_from
      description: |
        Filter the summary list of used discount types by submitted date of the order.
        The discount type must have been used on orders submitted on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-31-01'
    parameters_submittedAtTo-3:
      in: query
      name: submitted_at_to
      description: |
        Filter the summary list of used discount types by submitted date of the order.
        The discount type must have been used on orders submitted on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-31-10'
    parameters_discountType:
      in: query
      name: discount_type
      description: |
        Filter the summary list of used discount types by the applied discount(s).
      required: false
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    discountAppliedFrom:
      in: query
      name: discount_applied_from
      description: |
        Filter the breakdown list of used discount types by the date the discount was applied.
        The discount type must have been applied on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-01'
    discountAppliedTo:
      in: query
      name: discount_applied_to
      description: |
        Filter the breakdown list of used discount types by the date the discount was applied.
        The discount type must have been applied on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-31'
    parameters_siteId-39:
      in: query
      name: site_id
      description: Filter the breakdown list of used discount types by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-6:
      in: query
      name: revenue_date_from
      description: |
        Filter the breakdown list of used discount types by revenue date of the order.
        The discount type must have been used on orders with bookings on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-01'
    parameters_revenueDateTo-6:
      in: query
      name: revenue_date_to
      description: |
        Filter the breakdown list of used discount types by revenue date of the order.
        The discount type must have been used on orders with bookings on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-31'
    parameters_submittedAtFrom-4:
      in: query
      name: submitted_at_from
      description: |
        Filter the breakdown list of used discount types by submitted date of the order.
        The discount type must have been used on orders submitted on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-01'
    parameters_submittedAtTo-4:
      in: query
      name: submitted_at_to
      description: |
        Filter the breakdown list of used discount types by submitted date of the order.
        The discount type must have been used on orders submitted on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2023-10-31'
    parameters_appliedBy:
      in: query
      name: applied_by
      description: |
        Filter the breakdown list of used discount types by the user who applied the discount type.
      required: false
      schema:
        type: string
        format: uuid
    parameters_discountType-2:
      in: query
      name: discount_type
      description: |
        Filter the breakdown list of used discount types by the applied discount(s).
      required: false
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_siteId-40:
      in: query
      name: site_id
      description: Retrieve the deposit ledger details for this site.
      schema:
        type: string
        format: uuid
    parameters_date-6:
      in: query
      name: date
      description: Retrieve the deposit ledger details as at this date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    parameters_siteId-41:
      in: query
      name: site_id
      description: Retrieve the ledger voucher details for this site.
      schema:
        type: string
        format: uuid
    parameters_date-7:
      in: query
      name: date
      description: Retrieve the ledger voucher details as at this date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    parameters_siteId-42:
      in: query
      name: site_id
      description: Filter the list of items by site.
      schema:
        type: string
        format: uuid
    parameters_offeringType-3:
      in: query
      name: offering_type
      description: Filter by the offering type.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_offeringId-5:
      in: query
      name: offering_id
      description: Filter by the offering ID.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_offeringCategory:
      in: query
      name: offering_category
      description: Filter by the offering's category.
      schema:
        type: string
    parameters_soldById:
      in: query
      name: sold_by_id
      description: Filter by the ID of the user who sold the item.
      schema:
        type: array
        items:
          type: string
      explode: false
    parameters_orderStatus:
      in: query
      name: order_status
      description: Filter by the status of the order.
      schema:
        type: string
    parameters_status-8:
      in: query
      name: status
      description: Filter by the status of the item.
      schema:
        type: string
    parameters_revenueDateFrom-7:
      in: query
      name: revenue_date_from
      description: Filter to items with an order revenue date on or after this date.
      schema:
        type: string
        format: date
    parameters_revenueDateTo-7:
      in: query
      name: revenue_date_to
      description: Filter to items with an order revenue date on or before this date.
      schema:
        type: string
        format: date
    parameters_orderSubmittedAtFrom-2:
      in: query
      name: order_submitted_at_from
      description: Filter on orders with a submitted date on or after this time.
      schema:
        type: string
        format: date-time
    parameters_orderSubmittedAtTo-2:
      in: query
      name: order_submitted_at_to
      description: Filter on orders with a submitted date before this time.
      schema:
        type: string
        format: date-time
    parameters_orderLabel:
      in: query
      name: order_label
      description: Filter to items in orders with these labels.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_itemDateFrom-2:
      in: query
      name: item_date_from
      description: Filter on items which are booked in for on or after this date.
      schema:
        type: string
        format: date
    parameters_itemDateTo-2:
      in: query
      name: item_date_to
      description: Filter on items which are booked in for before this date.
      schema:
        type: string
        format: date
    parameters_practitionerId-6:
      in: query
      name: practitioner_id
      description: Filter to items assigned to these practitioners.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_roomId-4:
      in: query
      name: room_id
      description: Filter to items assigned to these rooms.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_zoneId-5:
      in: query
      name: zone_id
      description: Filter to items assigned to resources in these zones.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_siteId-43:
      in: query
      name: site_id
      description: Filter the list of baskets by site.
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-8:
      in: query
      name: revenue_date_from
      description: Filter to baskets with a revenue date on or after this date.
      schema:
        type: string
        format: date
    parameters_revenueDateTo-8:
      in: query
      name: revenue_date_to
      description: Filter to baskets with a revenue date on or before this date.
      schema:
        type: string
        format: date
    parameters_submittedAtFrom-5:
      in: query
      name: submitted_at_from
      description: Filter to baskets submitted on or after this date.
      schema:
        type: string
        format: date
    parameters_submittedAtTo-5:
      in: query
      name: submitted_at_to
      description: Filter to baskets submitted on or before this date.
      schema:
        type: string
        format: date
    parameters_siteId-44:
      in: query
      name: site_id
      description: Filter the list of sessions by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_id-2:
      in: query
      name: id
      description: Include only sessions with this ID.
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_date-8:
      in: query
      name: date
      description: Include sessions on this date.
      schema:
        type: string
        format: date
        example: '2023-05-05'
    parameters_startTimeFrom:
      in: query
      name: start_time_from
      description: Include sessions starting on or after this date.
      schema:
        type: string
        format: date-time
    parameters_startTimeTo:
      in: query
      name: start_time_to
      description: Include sessions starting before this date.
      schema:
        type: string
        format: date-time
    parameters_sessionTypeId-3:
      in: query
      name: session_type_id
      description: Include sessions of this type.
      schema:
        type: string
        format: mongo-id
    parameters_recurrenceGroupId-2:
      in: query
      name: recurrence_group_id
      description: Include sessions with this recurrence group ("session time").
      schema:
        type: string
        format: mongo-id
    parameters_roomId-5:
      in: query
      name: room_id
      description: Include sessions taking place in this room.
      schema:
        type: string
        format: mongo-id
    parameters_practitionerId-7:
      in: query
      name: practitioner_id
      description: Include sessions carried out by this practitioner.
      schema:
        type: string
        format: mongo-id
    parameters_zoneId-6:
      in: query
      name: zone_id
      description: Include sessions taking place in this zone.
      schema:
        type: string
        format: mongo-id
    parameters_includeCancelled:
      in: query
      name: include_cancelled
      description: Include cancelled sessions.
      schema:
        type: boolean
    parameters_cancelled:
      in: query
      name: cancelled
      description: Only return cancelled sessions.
      schema:
        type: boolean
    parameters_includeBookings-2:
      in: query
      name: include_bookings
      description: Include bookings in the response.
      schema:
        type: boolean
    parameters_siteId-45:
      in: query
      name: site_id
      description: Filter the summary of revenue by centre by site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-9:
      in: query
      name: revenue_date_from
      description: Filter to baskets with revenues on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-05-01'
    parameters_revenueDateTo-9:
      in: query
      name: revenue_date_to
      description: Filter to baskets with revenues on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-05-31'
    parameters_labels:
      in: query
      name: labels
      description: |
        Filter to baskets with the given labels. 
        This can be a comma separated list of label IDs, or 'none' to filter on baskets that don't have any labels.
      required: false
      explode: false
      schema:
        type: array
        items:
          type: string
          format: mongo-id
    parameters_revenueDateFrom-10:
      in: query
      name: revenue_date_from
      description: Include revenues on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-03-01'
    parameters_revenueDateTo-10:
      in: query
      name: revenue_date_to
      description: Include revenues on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-03-31'
    parameters_itemDateFrom-3:
      in: query
      name: item_date_from
      description: Include items taking place on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-03-01'
    parameters_itemDateTo-3:
      in: query
      name: item_date_to
      description: Include items taking place on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-03-31'
    parameters_labels-2:
      in: query
      name: labels
      description: Filter to baskets with the given labels.
      required: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_siteId-46:
      in: query
      name: site_id
      description: Include data for the given site ID(s).
      required: false
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_dateFrom-3:
      name: date_from
      in: query
      description: The date from which to start the report.
      required: true
      schema:
        type: string
        format: date
      example: '2019-01-01'
    parameters_dateTo-3:
      name: date_to
      in: query
      description: The date to which to end the report.
      required: true
      schema:
        type: string
        format: date
      example: '2019-12-31'
    authenticatableId:
      name: authenticatable_id
      in: query
      description: |
        Optional user filter. When provided, only authentication events
        for the given user are returned; omit to see every authentication
        attempt across the organisation in the date range.
      required: false
      schema:
        type: string
        format: uuid
    loginSuccessful:
      name: login_successful
      in: query
      description: Filter the report by whether the login was successful or not.
      required: false
      schema:
        type: boolean
      example: true
    parameters_submittedAtFrom-6:
      in: query
      name: submitted_at_from
      description: Include revenues for orders submitted on or after this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-03-31'
    parameters_submittedAtTo-6:
      in: query
      name: submitted_at_to
      description: Include revenues for orders submitted on or before this date.
      required: false
      schema:
        type: string
        format: date
        example: '2024-03-31'
    parameters_salesChannel:
      in: query
      name: sales_channel
      description: Include revenues from the given sales channel(s).
      required: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      explode: false
    parameters_revenueCentre:
      in: query
      name: revenue_centre
      description: Include revenues with the selected revenue centre(s).
      required: false
      schema:
        type: array
        items:
          type: string
      explode: false
    parameters_offeringType-4:
      in: query
      name: offering_type
      description: Include items of this type.
      required: false
      schema:
        type: array
        items:
          type: string
          example: appointment
      explode: false
    parameters_siteId-47:
      in: query
      name: site_id
      description: Filter the projected membership revenue report by site
      schema:
        type: string
        format: uuid
      required: true
    parameters_date-9:
      in: query
      name: date
      description: The date to get the projected membership revenue report for
      schema:
        type: string
        format: date
        example: '2023-05-05'
      required: true
    membershipTypeIds:
      in: query
      name: membership_type_ids
      description: Filter the projected membership revenue report by membership type
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    billingFrequency:
      in: query
      name: billing_frequency
      description: Filter the projected membership revenue report by billing frequency
      schema:
        type: array
        items:
          type: string
          enum:
            - P1M
            - P3M
            - P6M
            - P1Y
      explode: false
    manualPayments:
      in: query
      name: manual_payments
      description: Filter the projected membership revenue report by manual payments
      schema:
        type: boolean
    parameters_siteId-48:
      in: query
      name: site_id
      description: Filter the projected membership revenue by month report by site
      schema:
        type: string
        format: uuid
      required: true
    parameters_date-10:
      in: query
      name: date
      description: The date to get the projected membership revenue by month report for
      schema:
        type: string
        format: date
        example: '2023-05-05'
      required: true
    parameters_membershipTypeIds:
      in: query
      name: membership_type_ids
      description: Filter the projected membership revenue by month report by membership type
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
    parameters_billingFrequency:
      in: query
      name: billing_frequency
      description: Filter the projected membership revenue by month report by billing frequency
      schema:
        type: array
        items:
          type: string
          enum:
            - P1M
            - P3M
            - P6M
            - P1Y
      explode: false
    parameters_manualPayments:
      in: query
      name: manual_payments
      description: Filter the projected membership revenue by month report by manual payments
      schema:
        type: boolean
    parameters_siteId-49:
      in: query
      name: site_id
      required: false
      schema:
        type: string
      description: Filter orders by the site they belong to
    parameters_itemDate:
      in: query
      name: item_date
      schema:
        type: string
        format: date
      description: Filter on orders with items on this date.
    parameters_siteId-50:
      in: query
      name: site_id
      description: Restrict the report to membership credits associated with the given site. Omit to include credits across every site the caller's API key can access; the response groups them under their own `site_id` field.
      schema:
        type: string
        format: uuid
    parameters_status-9:
      in: query
      name: status
      description: |
        Filter credits by their computed status. Supports a single value or an array of values.
      required: false
      schema:
        oneOf:
          - type: string
            enum:
              - redeemable
              - redeemed
              - revoked
              - expired
          - type: array
            items:
              type: string
              enum:
                - redeemable
                - redeemed
                - revoked
                - expired
    parameters_membershipTypeId-2:
      in: query
      name: membership_type_id
      description: Filter credits by the membership type.
      required: false
      schema:
        type: string
        format: uuid
    membershipStatus:
      in: query
      name: membership_status
      description: |
        Filter credits by the current status of the associated membership.
      required: false
      schema:
        type: string
        enum:
          - active
          - inactive
          - expired
          - upcoming
          - needs_attention
          - reserved
    multiUse:
      in: query
      name: multi_use
      description: Filter credits by whether they are multi-use.
      required: false
      schema:
        type: boolean
    issuedAtFrom:
      in: query
      name: issued_at_from
      description: |
        Filter credits issued on or after this date. The date is interpreted
        in the site's local timezone.
      required: false
      schema:
        type: string
        format: date
        example: '2026-01-01'
    issuedAtTo:
      in: query
      name: issued_at_to
      description: |
        Filter credits issued on or before this date. The date is interpreted
        in the site's local timezone.
      required: false
      schema:
        type: string
        format: date
        example: '2026-03-31'
    parameters_sort-4:
      in: query
      name: sort
      description: The field to sort the results by.
      required: false
      schema:
        type: string
    parameters_siteId-51:
      in: query
      name: site_id
      description: Restrict the report to course credits belonging to the given site. Required, as the report resolves the site's course types to determine which credits to include.
      required: true
      schema:
        type: string
        format: uuid
    parameters_courseTypeId:
      in: query
      name: course_type_id
      description: Filter credits by the course type they were purchased from.
      required: false
      schema:
        type: string
        format: object-id
    parameters_customerId:
      in: query
      name: customer_id
      schema:
        type: string
        format: uuid
      description: Filters memberships belonging to the specified customer
    archived:
      in: query
      name: archived
      description: When `true`, only archived (soft-deleted) memberships are returned
      schema:
        type: boolean
    parameters_siteId-52:
      in: query
      name: site_id
      schema:
        type: string
      description: The site ID to filter against
    parameters_status-10:
      in: query
      name: status
      schema:
        type: array
        items:
          type: string
      explode: false
      style: form
      description: The status of the membership
    membershipTypeIdDeprecated:
      in: query
      deprecated: true
      name: membership_type_id
      schema:
        type: string
        format: uuid
      description: |
        Deprecated. Use `membership_type_ids` instead.
    parameters_membershipTypeIds-2:
      in: query
      name: membership_type_ids
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      style: form
      description: The membership type IDs to filter against. Separate multiple IDs with a comma.
    membershipRateIds:
      in: query
      name: membership_rate_ids
      schema:
        type: array
        items:
          type: string
          format: uuid
      explode: false
      style: form
      description: |
        Restrict the result to memberships on the given membership rates.
        Pass one or more `MembershipRate` IDs separated by commas. When
        omitted, all rates are returned.
    parameters_createdAtFrom-2:
      in: query
      name: created_at_from
      schema:
        type: string
        format: date
      description: Filter memberships created no earlier than the given date
    parameters_createdAtTo-2:
      in: query
      name: created_at_to
      schema:
        type: string
        format: date
      description: Filter memberships created no later than the given date
    nextBillingDateFrom:
      in: query
      name: next_billing_date_from
      schema:
        type: string
        format: date
      description: Filter memberships due for billing no earlier than the given date
    nextBillingDateTo:
      in: query
      name: next_billing_date_to
      schema:
        type: string
        format: date
      description: Filter memberships due for billing no later than the given date
    endDateFrom:
      in: query
      name: end_date_from
      schema:
        type: string
        format: date
      description: Filter memberships that end no earlier than the given date
    endDateTo:
      in: query
      name: end_date_to
      schema:
        type: string
        format: date
      description: Filter memberships that end no later than the given date
    attentionReason:
      in: query
      name: attention_reason
      schema:
        type: string
      description: The reason why this membership needs attention
    parameters_manualPayments-2:
      in: query
      name: manual_payments
      schema:
        type: boolean
      description: Whether to only show membership types that have auto-payments disabled
    parameters_billingFrequency-2:
      in: query
      name: billing_frequency
      schema:
        type: array
        items:
          type: string
      explode: false
      style: form
      description: The membership billing frequency to filter against
    rateId:
      in: query
      name: rate_id
      schema:
        type: array
        items:
          type: string
      explode: false
      style: form
      description: The membership rate to filter against
    membershipNumber:
      in: query
      name: membership_number
      schema:
        type: string
      description: The membership number to filter against
    externalRef:
      in: query
      name: external_ref
      schema:
        type: string
      description: The external reference to filter against
      example: '1234567890'
    parameters_organisationId-3:
      in: query
      name: organisation_id
      schema:
        type: string
        format: uuid
      description: Filter results by the given organisation ID
    onBehalfOf:
      in: header
      name: X-Trybe-On-Behalf-Of
      schema:
        type: string
        format: uuid
      description: The user ID of the user the request is made on behalf of.
    membershipId:
      in: path
      name: membershipId
      description: The ID of the membership
      required: true
      schema:
        type: string
        format: uuid
    parameters_brand_id:
      in: query
      name: brand_id
      description: Filters membership types that are associated with the given brand ID
      schema:
        type: string
    parameters_site_id:
      in: query
      name: site_id
      description: Filters membership types that are associated with the given site ID
      schema:
        type: string
    public:
      in: query
      name: public
      deprecated: true
      description: When `true`, only public membership types are returned
      schema:
        type: boolean
    auto_payments:
      in: query
      name: auto_payments
      description: When `true`, only membership types that support automatic payments are returned
      schema:
        type: boolean
    terms:
      in: query
      name: terms
      description: When `true`, only membership types that have terms and conditions are returned
      schema:
        type: boolean
    parameters_query-16:
      in: query
      name: query
      description: Filters membership types with a similar name to the given value
      schema:
        type: string
    parameters_membershipTypeId-3:
      in: path
      name: membershipTypeId
      description: The ID of the `MembershipType`.
      schema:
        type: string
        format: uuid
      required: true
    parameters_membership_type_id:
      in: query
      name: membership_type_id
      description: Filter membership rates by membership type ID
      schema:
        type: string
    parameters_site_id-2:
      in: query
      name: site_id
      description: Filters membership rates that belong to a membership rate that has been enabled for the given site
      schema:
        type: string
        format: uuid
    parameters_brand_id-2:
      in: query
      name: brand_id
      description: Filters membership rates that belong to a membership rate that has been enabled for the given site
      schema:
        type: string
        format: uuid
    parameters_query-17:
      in: query
      name: query
      description: Filters membership rates with a similar name to the given value
      schema:
        type: string
    parameters_brandId:
      in: query
      name: brand_id
      description: Filter membership credit rules by brand ID
      schema:
        type: string
        format: uuid
    parameters_membershipTypeId-4:
      in: query
      name: membership_type_id
      description: Filter membership credit rules by membership type ID
      schema:
        type: string
        format: uuid
    issueOnSignup:
      in: query
      name: issue_on_signup
      description: When `true`, only membership credit rules that are issued on signup are returned
      schema:
        type: boolean
    creditRuleId:
      name: creditRuleId
      in: path
      description: The ID of the membership credit rule
      required: true
      schema:
        type: string
        format: uuid
    chargeId:
      in: path
      name: chargeId
      description: The ID of the charge
      required: true
      schema:
        type: string
        format: uuid
    twofaEnabled:
      in: query
      name: twofa_enabled
      description: Filter users according to whether they have two-factor authentication enabled.
      required: false
      schema:
        type: boolean
    twofaDisabled:
      in: query
      name: twofa_disabled
      description: Filter users according to whether they do not shave two-factor authentication enabled.
      required: false
      schema:
        type: boolean
    managedBySso:
      in: query
      name: managed_by_sso
      description: Filter users according to whether they are managed by SSO.
      required: false
      schema:
        type: boolean
    notManagedBySso:
      in: query
      name: not_managed_by_sso
      description: Filter users according to whether they are not managed by SSO.
      required: false
      schema:
        type: boolean
    parameters_query-18:
      in: query
      name: query
      description: |
        A search query to filter roles by. This will search the role name.
      required: false
      schema:
        type: string
    roleId:
      in: path
      name: roleId
      description: The ID of the `Role`
      required: true
      schema:
        type: string
        format: uuid
    commissionPackageId:
      in: path
      name: commissionPackageId
      required: true
      schema:
        type: string
        format: mongo-id
      description: The ID of the commission package.
    parameters_userId-3:
      in: query
      name: user_id
      description: Restrict results to assignments for a single user.
      required: false
      schema:
        type: string
        format: uuid
    userCommissionAssignmentId:
      name: userCommissionAssignmentId
      in: path
      required: true
      description: The unique identifier of the user commission assignment.
      schema:
        type: string
        format: mongo-id
    offeringSetId:
      in: path
      name: offeringSetId
      required: true
      schema:
        type: string
        format: mongo-id
      description: The ID of the offering set.
    parameters_appointmentEnquiryId:
      in: path
      name: appointmentEnquiryId
      description: The ID of the `AppointmentEnquiry` to retrieve.
      required: true
      schema:
        type: string
        format: mongo-id
    parameters_appointmentTypeId-3:
      in: path
      name: appointmentTypeId
      description: The ID of the `AppointmentType` to check availability for.
      required: true
      schema:
        type: string
        format: mongo-id
    parameters_date-11:
      in: path
      name: date
      description: |
        The date to check availability on, in `YYYY-MM-DD` format. The date
        is interpreted in the timezone of the site the appointment type
        belongs to.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-12'
    parameters_practitionerId-8:
      in: query
      name: practitioner_id
      description: |
        Optionally restrict the results to slots that can be offered by a
        specific practitioner. When omitted, all eligible practitioners are
        considered.
      required: false
      schema:
        type: string
        format: mongo-id
    quantity:
      in: query
      name: quantity
      description: |
        The number of appointment slots required at the same start time.
        Used when booking multiple guests onto the same appointment type.
        Defaults to `1`.
      required: false
      schema:
        type: integer
        minimum: 1
        example: 2
    parameters_areaBookingTypeId:
      in: path
      name: areaBookingTypeId
      description: The ID of the `AreaBookingType` to check availability for.
      required: true
      schema:
        type: string
        format: mongo-id
    parameters_dateFrom-4:
      in: query
      name: date_from
      description: The earliest start date to return slots for, in `YYYY-MM-DD` format.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-4:
      in: query
      name: date_to
      description: |
        The latest start date to return slots for, in `YYYY-MM-DD` format.
        The range is inclusive. We recommend keeping the range to 14 days
        or fewer for performance reasons.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-14'
    parameters_quantity:
      in: query
      name: quantity
      description: |
        The number of area-booking slots required at the same start time.
        Used when booking multiple guests onto the same area. Defaults to
        `1`.
      required: false
      schema:
        type: integer
        minimum: 1
        example: 2
    areaId:
      in: query
      name: area_id
      description: |
        Optionally restrict the results to slots that can be served by a
        specific area. When omitted, all eligible areas configured on the
        booking type are considered.
      required: false
      schema:
        type: string
        format: mongo-id
    terminalId:
      in: path
      name: terminalId
      description: The ID of the `PaymentTerminal` to update.
      required: true
      schema:
        type: string
        format: object-id
    parameters_customPaymentTypeId:
      name: customPaymentTypeId
      in: path
      required: true
      schema:
        type: string
      description: |
        The identifier of the Trybe payment type whose Guestline payment code mapping is being updated.
        Usually a `CustomPaymentType` ID, but may also be a system payment processor key (e.g. `stripe`)
        or a partner-specific identifier (e.g. `partner:hospitality-co`).
    parameters_revenueCentre-2:
      name: revenueCentre
      in: path
      required: true
      schema:
        type: string
      description: The ID of the Trybe revenue centre whose Guestline analysis code mapping is being updated.
    parameters_date-12:
      name: date
      in: query
      required: true
      description: |
        The date on which to inspect availability. Expressed as an ISO-8601
        date-time anchored in the site's local timezone. Only the date
        portion is significant — the endpoint always returns availability
        for the full day.
      schema:
        type: string
        format: date-time
      example: '2024-06-12T00:00:00+01:00'
    parameters_offeringType-5:
      name: offering_type
      in: query
      required: false
      description: |
        The type of offering to scope availability to. Required when
        `offering_id` is provided. When omitted, the response includes
        every practitioner, room and equipment item at the site and skips
        offering-specific calendars.
      schema:
        type: string
        enum:
          - appointment
          - area_booking
          - session
          - course
          - product
          - package
          - voucher
      example: appointment
    parameters_offeringId-6:
      name: offering_id
      in: query
      required: false
      description: |
        The identifier of an offering (e.g. an `AppointmentType` or
        `AreaBookingType`) to focus the response on. When supplied
        together with `offering_type`, the response includes the offering's
        calendar availability and only the practitioners, rooms and
        equipment associated with that offering.
      schema:
        type: string
        format: object-id
      example: 5e932c0901d210625e3a8766
    parameters_packageItemId:
      in: path
      name: packageItemId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        The ID of the package item — i.e. one of the child line items
        inside a parent package order item (a treatment slot inside a
        spa-day package, a class booking inside a series, etc.).
    voucherCode:
      in: path
      name: voucherCode
      required: true
      schema:
        type: string
      description: |
        The redeemable code printed on the voucher (e.g. `XJ4P-RT8M`). The
        code uniquely identifies the voucher within the site — there is no
        separate numeric ID.
    appointmentTagId:
      in: path
      name: appointmentTagId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        The unique identifier of the appointment tag. Tag IDs are stable
        once issued and can be referenced from appointment-type payloads.
    parameters_siteId-53:
      in: query
      name: site_id
      description: |
        Filter the report to a single `Site`. When omitted, fees across every
        site the authenticated user has access to are included.
      schema:
        type: string
        format: uuid
    partnerId:
      in: query
      name: partner_id
      required: true
      description: |
        Scope the export to the named partner. Accepts a partner key from
        the platform partner catalogue (or `ota` for the generic OTA
        bucket). Only baskets attributed to this partner are included —
        direct bookings are excluded. Required because the report is
        partner-attribution-driven and would otherwise return an empty
        file.
      schema:
        type: string
        example: ota
    parameters_siteId-54:
      in: query
      name: site_id
      description: |
        Filter the export to one or more `Site` IDs. Accepts a single ID or
        a comma-separated list. When omitted, orders across every site the
        authenticated user has access to are included.
      schema:
        type: string
    parameters_customerId-2:
      in: query
      name: customer_id
      description: Filter the export to a single customer.
      schema:
        type: string
        format: uuid
    parameters_status-11:
      in: query
      name: status
      description: |
        Filter the export by basket `status`. Accepts a single value or a
        comma-separated list. Defaults to `new`, `submitted` and `settled`.
      schema:
        type: string
        example: submitted,settled
    parameters_query-19:
      in: query
      name: query
      description: |
        A free-text search across the order reference, external reference,
        customer name and email, and the names of items in the order. When
        set, results are ordered by relevance.
      schema:
        type: string
    parameters_submittedAtFrom-7:
      in: query
      name: submitted_at_from
      description: |
        The earliest `submitted_at` date and time to include in the export
        (inclusive).
      schema:
        type: string
        format: date-time
    parameters_submittedAtTo-7:
      in: query
      name: submitted_at_to
      description: |
        The latest `submitted_at` date and time to include in the export
        (inclusive).
      schema:
        type: string
        format: date-time
    parameters_itemDateFrom-4:
      in: query
      name: item_date_from
      description: |
        Include orders that contain at least one item dated on or after this
        date.
      schema:
        type: string
        format: date
    parameters_itemDateTo-4:
      in: query
      name: item_date_to
      description: |
        Include orders that contain at least one item dated on or before this
        date.
      schema:
        type: string
        format: date
    parameters_revenueDateFrom-11:
      in: query
      name: revenue_date_from
      description: The earliest `revenue_date` to include in the export (inclusive).
      schema:
        type: string
        format: date
    parameters_revenueDateTo-11:
      in: query
      name: revenue_date_to
      description: The latest `revenue_date` to include in the export (inclusive).
      schema:
        type: string
        format: date
    parameters_labels-3:
      in: query
      name: labels
      description: |
        Filter by basket labels. Accepts a comma-separated list of label IDs;
        prefix an ID with `-` to exclude orders with that label, or pass
        `none` to match only orders with no labels at all.
      schema:
        type: string
    parameters_externalId:
      in: query
      name: external_id
      description: |
        Filter by an external ID in the form `key:value` (for example,
        `pms:RES-12345`).
      schema:
        type: string
    parameters_email-2:
      in: query
      name: email
      description: |
        When `true`, the rendered CSV will be emailed to the user who queued
        the job once it has finished generating. When `false` (the default)
        the file is only made available for download from the queued job.
      schema:
        type: boolean
        default: false
    parameters_siteIdFilter:
      in: query
      name: site_id
      required: false
      description: |
        Optional filter restricting the response to labels visible at the
        given site. When set, the response includes both labels with no
        site restriction (visible everywhere in the organisation) and
        labels explicitly scoped to this site via the label's
        `site_ids` list. When omitted, every label in the organisation
        is returned.
      schema:
        type: string
        format: uuid
    parameters_labelId:
      in: path
      name: labelId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        The unique identifier of the label. Label IDs are stable once
        issued and can be referenced from any record the label is
        attached to.
    parameters_revenueCentreId:
      in: path
      name: revenueCentreId
      required: true
      schema:
        type: string
      description: |
        The identifier of the revenue centre. System revenue centres use
        stable, lower-case slugs (`spa`, `deposit`, ...); custom ones are
        issued when the centre is created.
    parameters_salesChannelId:
      in: path
      name: salesChannelId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        The unique identifier of the sales channel. Sales channel IDs are
        stable once issued and can be referenced from orders, appointments,
        and other revenue-bearing records.
    parameters_siteId-55:
      in: query
      name: site_id
      description: Restrict the report to the given site.
      schema:
        type: string
        format: uuid
    parameters_dateFrom-5:
      in: query
      name: date_from
      description: |
        Restrict to occupancy on or after this date. Required. The range between
        `date_from` and `date_to` cannot exceed 60 days.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-5:
      in: query
      name: date_to
      description: Restrict to occupancy on or before this date. Required.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-30'
    bookableAreaIds:
      in: query
      name: bookable_area_ids
      description: A comma-separated list of bookable area IDs to restrict to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_zoneId-7:
      in: query
      name: zone_id
      description: A comma-separated list of zone IDs to restrict bookable areas to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_email-3:
      in: query
      name: email
      description: |
        If `true`, email the completed CSV to the authenticated user when the background job
        finishes. Defaults to `false`, in which case the queued job's output URL must be polled
        via the queued-jobs endpoint.
      schema:
        type: boolean
        default: false
    parameters_siteId-56:
      in: query
      name: site_id
      description: Restrict the report to baskets at the given site. Required.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-12:
      in: query
      name: revenue_date_from
      description: Restrict to baskets with a revenue date on or after this date.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_revenueDateTo-12:
      in: query
      name: revenue_date_to
      description: Restrict to baskets with a revenue date on or before this date.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-30'
    parameters_siteId-57:
      in: query
      name: site_id
      description: Restrict the report to charges at the given site.
      schema:
        type: string
        format: uuid
    completedFrom:
      in: query
      name: completed_from
      description: Restrict to charges completed on or after this time.
      schema:
        type: string
        format: date-time
    completedTo:
      in: query
      name: completed_to
      description: Restrict to charges completed on or before this time.
      schema:
        type: string
        format: date-time
    createdFrom:
      in: query
      name: created_from
      description: Restrict to charges created on or after this time.
      schema:
        type: string
        format: date-time
    createdTo:
      in: query
      name: created_to
      description: Restrict to charges created on or before this time.
      schema:
        type: string
        format: date-time
    parameters_revenueDateFrom-13:
      in: query
      name: revenue_date_from
      description: Restrict to charges with a revenue date on or after this date.
      schema:
        type: string
        format: date
    parameters_revenueDateTo-13:
      in: query
      name: revenue_date_to
      description: Restrict to charges with a revenue date on or before this date.
      schema:
        type: string
        format: date
    payoutDateFrom:
      in: query
      name: payout_date_from
      description: Restrict to charges with a payout date on or after this date.
      schema:
        type: string
        format: date
    payoutDateTo:
      in: query
      name: payout_date_to
      description: Restrict to charges with a payout date on or before this date.
      schema:
        type: string
        format: date
    parameters_status-12:
      in: query
      name: status
      description: |
        The charge status to include. Defaults to `complete` for the main charge list and to
        `all` for the pay-by-link variant.
      schema:
        type: string
        example: complete
    chargeableType:
      in: query
      name: chargeable_type
      description: Filter to charges against a specific chargeable type (e.g. `order`, `membership`).
      schema:
        type: string
    chargeType:
      in: query
      name: charge_type
      description: Filter to a particular charge type (e.g. `payment`, `refund`).
      schema:
        type: string
    parameters_processor:
      in: query
      name: processor
      description: Filter to charges that went through a specific payment processor (e.g. `adyen`, `stripe`, `cash`).
      schema:
        type: string
    detailsSource:
      in: query
      name: details_source
      description: Filter to charges where the payment details came from a specific source (e.g. `pay_by_link`).
      schema:
        type: string
    parameters_orderStatus-2:
      in: query
      name: order_status
      description: Filter to charges whose parent order has a specific status.
      schema:
        type: string
    createdBy:
      in: query
      name: created_by
      description: Filter to charges created by a specific user ID.
      schema:
        type: string
        format: object-id
    parameters_siteId-58:
      in: query
      name: site_id
      description: Restrict the report to commission earned at the given site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_dateFrom-6:
      in: query
      name: date_from
      description: Restrict to commission earned on or after this date.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-6:
      in: query
      name: date_to
      description: Restrict to commission earned on or before this date.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-30'
    earnerId:
      in: query
      name: earner_id
      description: |
        Restrict the report to a single earner (a `Practitioner` or
        `User`, per `earner_type`).
      required: false
      schema:
        type: string
    earnerType:
      in: query
      name: earner_type
      description: |
        Restrict the report to earners of this type. Combine with
        `earner_id` to disambiguate an id that could otherwise refer to
        either a `Practitioner` or a `User`.
      required: false
      schema:
        type: string
        enum:
          - practitioner
          - user
    parameters_dateFrom-7:
      in: query
      name: date_from
      description: Restrict to items on or after this date.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-7:
      in: query
      name: date_to
      description: Restrict to items on or before this date.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-30'
    parameters_practitionerId-9:
      in: query
      name: practitioner_id
      description: |
        Restrict the report to a single practitioner. Deprecated: prefer
        `earner_id` + `earner_type`, which also cover items sold by a
        plain `User` under a `sold` attribution rate.
      required: false
      deprecated: true
      schema:
        type: string
        format: uuid
    parameters_siteId-59:
      in: query
      name: site_id
      description: The site to compute the daily stats for.
      required: true
      schema:
        type: string
        format: uuid
    parameters_date-13:
      in: query
      name: date
      description: The date to compute the stats for. Defaults to today in the site's timezone if omitted.
      schema:
        type: string
        format: date
        example: '2026-06-15'
    parameters_siteId-60:
      in: query
      name: site_id
      description: |
        Restrict to charges at the given site. Defaults to the authenticated user's default
        site if omitted.
      schema:
        type: string
        format: uuid
    parameters_date-14:
      in: query
      name: date
      description: |
        The date the charges were completed on. Must be on or before today. Defaults to today
        in the site's timezone if omitted.
      schema:
        type: string
        format: date
        example: '2026-06-15'
    parameters_siteId-61:
      in: query
      name: site_id
      description: Restrict to baskets at the given site.
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-14:
      in: query
      name: revenue_date_from
      description: Restrict to baskets with a revenue date on or after this date.
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_revenueDateTo-14:
      in: query
      name: revenue_date_to
      description: Restrict to baskets with a revenue date on or before this date.
      schema:
        type: string
        format: date
        example: '2026-06-30'
    parameters_submittedAtFrom-8:
      in: query
      name: submitted_at_from
      description: Restrict to baskets submitted on or after this date.
      schema:
        type: string
        format: date
    parameters_submittedAtTo-8:
      in: query
      name: submitted_at_to
      description: Restrict to baskets submitted on or before this date.
      schema:
        type: string
        format: date
    parameters_siteId-62:
      in: query
      name: site_id
      description: The site to compute the voucher ledger for.
      required: true
      schema:
        type: string
        format: uuid
    parameters_dateFrom-8:
      in: query
      name: date_from
      description: Start of the date range covered by the ledger.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-8:
      in: query
      name: date_to
      description: End of the date range covered by the ledger.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-30'
    parameters_siteId-63:
      in: query
      name: site_id
      description: Restrict to items at the given site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-15:
      in: query
      name: revenue_date_from
      description: Restrict to items belonging to baskets with a revenue date on or after this date.
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_revenueDateTo-15:
      in: query
      name: revenue_date_to
      description: Restrict to items belonging to baskets with a revenue date on or before this date.
      schema:
        type: string
        format: date
        example: '2026-06-30'
    parameters_itemDateFrom-5:
      in: query
      name: item_date_from
      description: Restrict to items dated on or after this date.
      schema:
        type: string
        format: date
    parameters_itemDateTo-5:
      in: query
      name: item_date_to
      description: Restrict to items dated on or before this date.
      schema:
        type: string
        format: date
    parameters_orderSubmittedAtFrom-3:
      in: query
      name: order_submitted_at_from
      description: Restrict to items belonging to baskets submitted on or after this time.
      schema:
        type: string
        format: date-time
    parameters_orderSubmittedAtTo-3:
      in: query
      name: order_submitted_at_to
      description: Restrict to items belonging to baskets submitted on or before this time.
      schema:
        type: string
        format: date-time
    parameters_offeringType-6:
      in: query
      name: offering_type
      description: Filter to items of a particular offering type. Pass `all` to include every type (the default when filters omit this).
      schema:
        type: string
        example: appointment
    parameters_offeringIds:
      in: query
      name: offering_ids
      description: A comma-separated list of offering IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_revenueCentres:
      in: query
      name: revenue_centres
      description: A comma-separated list of revenue centre keys or IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
    parameters_siteId-64:
      in: query
      name: site_id
      description: The site to compute the overview for.
      required: true
      schema:
        type: string
        format: uuid
    parameters_dateFrom-9:
      in: query
      name: date_from
      description: |
        The first date in the overview. Required. The range between `date_from` and `date_to`
        cannot exceed 7 days.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-15'
    parameters_dateTo-9:
      in: query
      name: date_to
      description: The last date in the overview. Required.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-21'
    parameters_zoneId-8:
      in: query
      name: zone_id
      description: A comma-separated list of zone IDs to restrict practitioners and rooms to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_siteId-65:
      in: query
      name: site_id
      description: Restrict to pay-by-link payments at the given site.
      required: true
      schema:
        type: string
        format: uuid
    perPage:
      in: query
      name: per_page
      description: The number of payments to return per page. Defaults to 30.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 30
    parameters_createdFrom:
      in: query
      name: created_from
      description: Restrict to pay-by-link charges created on or after this date.
      schema:
        type: string
        format: date
    parameters_createdTo:
      in: query
      name: created_to
      description: Restrict to pay-by-link charges created on or before this date.
      schema:
        type: string
        format: date
    parameters_completedFrom:
      in: query
      name: completed_from
      description: Restrict to pay-by-link charges completed on or after this date.
      schema:
        type: string
        format: date
    parameters_completedTo:
      in: query
      name: completed_to
      description: Restrict to pay-by-link charges completed on or before this date.
      schema:
        type: string
        format: date
    parameters_revenueDateFrom-16:
      in: query
      name: revenue_date_from
      description: Restrict to pay-by-link charges whose underlying basket has a revenue date on or after this date.
      schema:
        type: string
        format: date
    parameters_revenueDateTo-16:
      in: query
      name: revenue_date_to
      description: Restrict to pay-by-link charges whose underlying basket has a revenue date on or before this date.
      schema:
        type: string
        format: date
    parameters_status-13:
      in: query
      name: status
      description: Filter to pay-by-link charges with a specific status. Defaults to `all`.
      schema:
        type: string
        example: complete
    parameters_sort-5:
      in: query
      name: sort
      description: Field to sort the list by.
      schema:
        type: string
        example: created_at
    parameters_sortOrder-2:
      in: query
      name: sort_order
      description: |
        Sort direction. `asc` returns oldest-first, `desc` returns
        newest-first. Combine with `sort` to control which column is
        sorted. Defaults to `asc`.
      schema:
        type: string
        enum:
          - asc
          - desc
        default: asc
    parameters_siteId-66:
      in: query
      name: site_id
      description: Restrict the report to the given site. Required.
      required: true
      schema:
        type: string
        format: uuid
    parameters_dateFrom-10:
      in: query
      name: date_from
      description: |
        Restrict to bookings on or after this date. Required. The range between
        `date_from` and `date_to` cannot exceed 31 days.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-10:
      in: query
      name: date_to
      description: Restrict to bookings on or before this date. Required.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-30'
    parameters_zoneId-9:
      in: query
      name: zone_id
      description: A comma-separated list of zone IDs to restrict practitioners to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_siteId-67:
      in: query
      name: site_id
      description: Restrict the report to baskets at the given site.
      schema:
        type: string
        format: uuid
    parameters_itemDateFrom-6:
      in: query
      name: item_date_from
      description: Restrict to baskets containing items dated on or after this date.
      schema:
        type: string
        format: date
    parameters_itemDateTo-6:
      in: query
      name: item_date_to
      description: Restrict to baskets containing items dated on or before this date.
      schema:
        type: string
        format: date
    parameters_labels-4:
      in: query
      name: labels
      description: A comma-separated list of order label IDs to filter on. Pass `none` to restrict to baskets with no order labels.
      explode: false
      schema:
        type: array
        items:
          type: string
    parameters_revenueCentre-3:
      in: query
      name: revenue_centre
      description: A comma-separated list of revenue centre keys or IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
    parameters_salesChannel-2:
      in: query
      name: sales_channel
      description: A comma-separated list of sales channel IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
      example: 69c128bf5a210879a60ac186,69c128bf5a210879a60ac187
    parameters_revenueCentre-4:
      in: query
      name: revenue_centre
      description: A comma-separated list of revenue centre keys or IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
      example: spa,retail
    parameters_siteId-68:
      in: query
      name: site_id
      description: Restrict the projection to baskets at the given site.
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-17:
      in: query
      name: revenue_date_from
      description: |
        Restrict to baskets with a revenue date on or after this date. Either this and
        `revenue_date_to` must be provided, or `item_date_from` and `item_date_to`. The total
        range cannot exceed 31 days.
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_roomIds:
      in: query
      name: room_ids
      description: A comma-separated list of room IDs to restrict to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_zoneId-10:
      in: query
      name: zone_id
      description: A comma-separated list of zone IDs to restrict rooms to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_siteId-69:
      in: query
      name: site_id
      description: The site to generate the run sheet for.
      required: true
      schema:
        type: string
        format: uuid
    parameters_date-15:
      in: query
      name: date
      description: The date the run sheet covers. Defaults to today in the site's timezone if omitted.
      required: true
      schema:
        type: string
        format: date
        example: '2026-06-15'
    parameters_practitionerId-10:
      in: query
      name: practitioner_id
      description: A comma-separated list of practitioner IDs to restrict the run sheet to.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_revenueDateFrom-18:
      in: query
      name: revenue_date_from
      description: Restrict to baskets with a revenue date on or after this date.
      schema:
        type: string
        format: date
        example: '2026-01-01'
    parameters_revenueDateTo-17:
      in: query
      name: revenue_date_to
      description: Restrict to baskets with a revenue date on or before this date.
      schema:
        type: string
        format: date
        example: '2026-12-31'
    parameters_siteId-70:
      in: query
      name: site_id
      description: Restrict to items at the given site.
      schema:
        type: string
        format: uuid
    parameters_revenueDateFrom-19:
      in: query
      name: revenue_date_from
      description: Restrict to items belonging to baskets with a revenue date on or after this date.
      schema:
        type: string
        format: date
        example: '2026-01-01'
    parameters_revenueDateTo-18:
      in: query
      name: revenue_date_to
      description: Restrict to items belonging to baskets with a revenue date on or before this date.
      schema:
        type: string
        format: date
        example: '2026-12-31'
    parameters_offeringType-7:
      in: query
      name: offering_type
      description: Filter to items of a particular offering type.
      schema:
        type: string
    parameters_siteId-71:
      in: query
      name: site_id
      description: The site whose Trybe Payments balance is being reported on.
      required: true
      schema:
        type: string
        format: uuid
    parameters_siteId-72:
      in: query
      name: site_id
      description: The site to list voucher codes for.
      required: true
      schema:
        type: string
        format: uuid
    parameters_perPage:
      in: query
      name: per_page
      description: The number of voucher codes to return per page (1-100). Defaults to 30.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 30
    parameters_code-4:
      in: query
      name: code
      description: Filter to voucher codes containing this substring (case-insensitive).
      schema:
        type: string
    parameters_status-14:
      in: query
      name: status
      description: A comma-separated list of voucher code statuses to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
    parameters_amount:
      in: query
      name: amount
      description: |
        Filter by code face amount (in minor units). Supports a comparison operator prefix,
        e.g. `>=10000`, `<5000`, `=2000`, or a bare value (interpreted as equality).
      schema:
        type: string
        example: '>=10000'
    parameters_balance:
      in: query
      name: balance
      description: Filter by remaining code balance (in minor units), using the same operator syntax as `amount`.
      schema:
        type: string
    parameters_voucherTypeId-2:
      in: query
      name: voucher_type_id
      description: A comma-separated list of voucher type IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: object-id
    parameters_fulfillmentStatus:
      in: query
      name: fulfillment_status
      description: Filter by voucher fulfillment status.
      schema:
        type: string
    parameters_createdSince:
      in: query
      name: created_since
      description: Filter to voucher codes created on or after this date-time.
      schema:
        type: string
        format: date-time
    parameters_expiredRangeFrom:
      in: query
      name: expired_range_from
      description: Filter to voucher codes whose expiry date falls on or after this date.
      schema:
        type: string
        format: date
    parameters_expiredRangeTo:
      in: query
      name: expired_range_to
      description: Filter to voucher codes whose expiry date falls strictly before this date.
      schema:
        type: string
        format: date
    parameters_siteId-73:
      in: query
      name: site_id
      description: Restrict the report to yielded sales at the given site.
      required: true
      schema:
        type: string
        format: uuid
    parameters_dateFrom-11:
      in: query
      name: date_from
      description: |
        Restrict to sales made on or after this date, in the site's local
        timezone.
      schema:
        type: string
        format: date
        example: '2026-06-01'
    parameters_dateTo-11:
      in: query
      name: date_to
      description: |
        Restrict to sales made on or before this date, in the site's local
        timezone.
      schema:
        type: string
        format: date
        example: '2026-06-30'
    search:
      in: query
      name: search
      description: |
        Restrict to sales whose order reference or offering name contains the
        given text, case-insensitively.
      schema:
        type: string
        example: massage
    parameters_offeringIds-2:
      in: query
      name: offering_ids
      description: A comma-separated list of offering IDs to filter on.
      explode: false
      schema:
        type: array
        items:
          type: string
    parameters_offeringTypes:
      in: query
      name: offering_types
      description: A comma-separated list of offering types to filter on.
      explode: false
      example: appointment,area_booking
      schema:
        type: array
        items:
          type: string
          enum:
            - appointment
            - area_booking
            - session
            - package
    yieldRuleIds:
      in: query
      name: yield_rule_ids
      description: |
        A comma-separated list of yield rule IDs to filter on. Matches the rule
        recorded at the time of sale, so a rule that has since been deleted
        still matches its historical sales.
      explode: false
      schema:
        type: array
        items:
          type: string
          format: uuid
    tiers:
      in: query
      name: tiers
      description: A comma-separated list of reporting tiers to filter on.
      explode: false
      example: high,peak
      schema:
        type: array
        items:
          type: string
          enum:
            - low
            - high
            - peak
    blockedTimePresetId:
      name: blockedTimePresetId
      in: path
      required: true
      description: The ID of the blocked-time preset.
      schema:
        type: string
        format: object-id
    dateFromRequired:
      name: date_from
      in: query
      required: true
      description: |
        First date to include in the listing, inclusive. ISO-8601
        `YYYY-MM-DD` in the site's timezone.
      schema:
        type: string
        format: date
    dateToRequired:
      name: date_to
      in: query
      required: true
      description: |
        Last date to include in the listing, inclusive. ISO-8601
        `YYYY-MM-DD` in the site's timezone.
      schema:
        type: string
        format: date
    blockedTimeId:
      name: blockedTimeId
      in: path
      required: true
      description: The ID of the blocked time.
      schema:
        type: string
        format: object-id
    parameters_offeringId-7:
      in: query
      name: offering_id
      required: false
      description: |
        Filter results to course types whose `offerings` include the given
        offering ID. Comma-separate to OR multiple IDs (e.g.
        `offering_id=abc,def`).
      schema:
        type: string
      example: 5f1234567890abcdef123456
    parameters_categoryId-6:
      in: query
      name: category_id
      required: false
      description: |
        Filter results to course types that include the given category in
        their `category_ids`. Comma-separate to OR multiple categories.
      schema:
        type: string
      example: 5f1234567890abcdef123456
    siteIdPath:
      name: siteId
      in: path
      required: true
      description: The ID of the site the offering belongs to.
      schema:
        type: string
        format: uuid
    appointmentTypeIdPath:
      name: appointmentTypeId
      in: path
      required: true
      description: The ID of the appointment type to check availability for.
      schema:
        type: string
        format: mongo-id
    dateTimeFromRequired:
      name: date_time_from
      in: query
      required: true
      description: |
        Earliest date-time to consider, in ISO-8601 format in the
        offering's site timezone (e.g. `2026-06-01T09:00:00+01:00`).
      schema:
        type: string
    dateTimeToRequired:
      name: date_time_to
      in: query
      required: true
      description: |
        Latest date-time to consider. Must be strictly after
        `date_time_from`. For per-day endpoints, the range may not
        exceed a single day.
      schema:
        type: string
    durationOverride:
      name: duration
      in: query
      required: false
      description: |
        Override the offering's default duration, in minutes. Must be
        positive.
      schema:
        type: integer
        minimum: 1
    practitionerIdFilter:
      name: practitioner_id
      in: query
      required: false
      description: |
        Limit slots to a single practitioner. The practitioner must be
        eligible to deliver the appointment type.
      schema:
        type: string
    excludeAppointmentsFilter:
      name: exclude_appointments
      in: query
      required: false
      description: |
        Comma-separated list of existing appointment IDs to ignore when
        calculating resource conflicts. Use this when re-checking
        availability during an appointment-edit flow so the appointment
        being edited doesn't block itself.
      schema:
        type: string
    excludeBasketItemsFilter:
      name: exclude_basket_items
      in: query
      required: false
      description: |
        Comma-separated list of basket-item IDs to ignore. Mirrors
        `exclude_appointments` / `exclude_bookings` but for items
        already in the caller's basket.
      schema:
        type: string
    basketIdFilter:
      name: basket_id
      in: query
      required: false
      description: |
        Basket ID to scope the check to. The server reads the basket's
        coupon codes (for price computation) and excludes its items
        when computing conflicts.
      schema:
        type: string
    guestIdFilter:
      name: guest_id
      in: query
      required: false
      description: |
        Guest ID to attribute the slot to. Drives per-guest booking
        limits.
      schema:
        type: string
    requiredQuantityFilter:
      name: required_quantity
      in: query
      required: false
      description: |
        Number of guests/instances the slot must accommodate. Defaults
        to 1.
      schema:
        type: integer
        minimum: 1
    areaBookingTypeIdPath:
      name: areaBookingTypeId
      in: path
      required: true
      description: The ID of the area booking type to check availability for.
      schema:
        type: string
        format: mongo-id
    excludeBookingsFilter:
      name: exclude_bookings
      in: query
      required: false
      description: |
        Comma-separated list of existing area-booking IDs to ignore
        when calculating area conflicts.
      schema:
        type: string
    quantityFilter:
      name: quantity
      in: query
      required: false
      description: |
        Number of guests/instances the slot must accommodate. Defaults
        to 1.
      schema:
        type: integer
        minimum: 1
    parameters_dateFromRequired:
      name: date_from
      in: query
      required: true
      description: |
        First date in the requested window (inclusive), ISO-8601
        `YYYY-MM-DD` in the offering's site timezone.
      schema:
        type: string
        format: date
    parameters_dateToRequired:
      name: date_to
      in: query
      required: true
      description: |
        Last date in the requested window (inclusive). For most
        offerings the range may not exceed 31 days.
      schema:
        type: string
        format: date
    offeringIdRequired:
      name: offering_id
      in: query
      required: true
      description: |
        The offering whose date-by-date availability should be returned.
        Must be paired with `offering_type` so the platform knows which
        catalogue to look the ID up in (appointments, sessions or
        packages). Returns `422` if the ID does not resolve to a live
        offering of the supplied type.
      schema:
        type: string
        example: 5dcb47800000000000000010
    offeringTypeRequired:
      name: offering_type
      in: query
      required: true
      description: The kind of offering `offering_id` refers to.
      schema:
        type: string
        enum:
          - appointment
          - session
          - package
          - area_booking
    partnerIdFilter:
      name: partner_id
      in: query
      required: false
      description: |
        Restrict the check to the given partner's allotment. Pass the
        partner's `partner_id` (e.g. `ota`).
      schema:
        type: string
    packageIdPath:
      name: packageId
      in: path
      required: true
      description: The ID of the package to check availability for.
      schema:
        type: string
        format: mongo-id
    packageChoiceIdPath:
      name: choiceId
      in: path
      required: true
      description: |
        The ID of the package item choice (the slot in the package
        that's being filled).
      schema:
        type: string
        format: mongo-id
    productIdPath:
      name: productId
      in: path
      required: true
      description: The ID of the product to check availability for.
      schema:
        type: string
        format: mongo-id
    sessionTypeIdPath:
      name: sessionTypeId
      in: path
      required: true
      description: The ID of the session type to check availability for.
      schema:
        type: string
        format: mongo-id
    parameters_paymentId-3:
      in: query
      name: payment_id
      description: |
        When set, scopes the refundable items list to what can be refunded
        against this payment. Tips are only included when linked to the
        payment; order items may also be filtered when payment item revenues
        are available. Required by the refund modal for multi-payment orders
        so money cannot leave via a different payment method than it arrived on.
      required: false
      schema:
        type: string
        format: object-id
    parameters_revenueCentre-5:
      in: query
      name: revenue_centre
      description: |
        When set, only refunds that allocate any amount to this revenue
        centre are returned. Useful for surfaces that only care about a
        single centre (for example tip refunds).
      required: false
      schema:
        type: string
        example: tip
    refundId:
      name: refundId
      in: path
      required: true
      schema:
        type: string
        format: object-id
      description: The ID of the refund.
    partnerConfigId:
      name: partnerConfigId
      in: path
      required: true
      description: The ID of the partner config.
      schema:
        type: string
        format: object-id
    parameters_availabilityRuleId:
      name: availabilityRuleId
      in: path
      required: true
      description: The ID of the availability rule.
      schema:
        type: string
        format: object-id
    parameters_date-16:
      in: query
      name: date
      required: true
      description: |
        The ISO 8601 date (`YYYY-MM-DD`) the caller wants rules for. The
        date is interpreted in the practitioner's timezone, NOT the
        caller's. There is no range support — pass one date per request.
      schema:
        type: string
        format: date
      example: '2026-06-01'
    organisationIdRequired:
      name: organisation_id
      in: query
      required: true
      description: |
        ID of the organisation to scope the listing to. Categories and
        appointment tags are organisation-level, not site-level — pass
        the org that owns the relevant sites.
      schema:
        type: string
        format: uuid
    dateOptional:
      name: date
      in: query
      required: false
      description: |
        Optional date (YYYY-MM-DD) used to scope the listing to
        offerings that have availability on that day.
      schema:
        type: string
        format: date
    categoryIdFilter:
      name: category_id
      in: query
      required: false
      description: |
        Filter the result to a single offering category.
      schema:
        type: string
    parameters_partnerIdFilter:
      name: partner_id
      in: query
      required: false
      description: |
        Restrict the listing to offerings the given partner is allowed
        to sell. Pass the partner key (e.g. `ota`).
      schema:
        type: string
    paymentTypeId:
      name: paymentTypeId
      in: path
      required: true
      schema:
        type: string
      description: |
        The ID of the Trybe payment type whose Mews accounting category mapping is being updated. Either a Trybe-defined custom payment type ID, a system payment type ID, or a `partner:<key>` value for partner payment types.
    parameters_revenueCentre-6:
      name: revenueCentre
      in: path
      required: true
      schema:
        type: string
      description: The ID of the Trybe revenue centre whose Mews accounting category and tax code mapping is being updated. Either a Trybe-defined revenue centre ID or a system revenue centre ID (e.g. `deposits`, `gift_cards`).
    parameters_paymentTypeId:
      name: paymentTypeId
      in: path
      required: true
      schema:
        type: string
      description: |
        The ID of the Trybe payment type whose Opera FIAS selector mapping is being updated. Either a Trybe-defined custom payment type ID, a system payment selector (e.g. `deposit_redemption`, `voucher_difference`), or a `partner:<key>` value for partner payment types.
    parameters_revenueCentre-7:
      name: revenueCentre
      in: path
      required: true
      schema:
        type: string
      description: |
        The ID of the Trybe revenue centre whose Opera FIAS sales outlet and department mapping is being updated. Either a Trybe-defined revenue centre ID or a system revenue centre ID (e.g. `deposits`, `gift_cards`).
    parameters_code-5:
      in: query
      name: code
      required: false
      description: |
        Exact-match filter on the redemption code. Pair with pagination if
        you expect more than one match.
      schema:
        type: string
        example: SUMMER2026
    releaseAssetId:
      in: path
      name: version
      required: true
      description: |
        Numeric GitHub asset ID for the release artefact to download. The
        ID is provided in the `assets[].download_url` of
        `GET /shop/esc-pos/latest-release` (or the equivalent `fias-relay`
        feed).
      schema:
        type: string
        example: '123456789'
    parameters_releaseAssetId:
      in: path
      name: version
      required: true
      description: |
        Numeric GitHub asset ID for the release artefact to download. The
        ID is provided in the `assets[].download_url` of
        `GET /shop/fias-relay/latest-release`.
      schema:
        type: string
        example: '987654321'
    intakeFormQuestionId:
      name: intakeFormQuestionId
      in: path
      required: true
      description: The unique identifier of the `IntakeFormQuestion`.
      schema:
        type: string
        format: object-id
    toastId:
      in: path
      name: toastId
      required: true
      description: |
        The unique identifier of the `IntegrationConfig` representing the
        Toast POS integration on the calling site. The config's `provider`
        must be `toast`; calls against a config with any other provider
        return `404`.
      schema:
        type: string
        format: object-id
    parameters_date-17:
      in: query
      name: date
      required: true
      description: |
        Any ISO 8601 calendar date inside the month to summarise. The
        response covers the full month containing this date, computed in
        the offering's timezone.
      schema:
        type: string
        format: date
        example: '2026-05-01'
    parameters_offeringType-8:
      in: query
      name: offering_type
      required: true
      description: The offering type the `offering_id` belongs to.
      schema:
        type: string
        enum:
          - appointment
          - area_booking
          - package
          - session
    parameters_offeringId-8:
      in: query
      name: offering_id
      required: true
      description: ID of the offering to summarise.
      schema:
        type: string
    orderRef:
      in: path
      name: orderRef
      required: true
      description: |
        The short customer-facing order reference (e.g. `TRY1234`). The
        lookup is case-insensitive: Trybe upper-cases the value before
        matching against stored references.
      schema:
        type: string
        example: TRY1234
    parameters_siteIdFilter-2:
      in: query
      name: site_id
      required: false
      description: |
        Optional UUID filter to scope the lookup to a single site. By
        default the search runs across every site the calling user belongs
        to and returns the first match.
      schema:
        type: string
        format: uuid
    parameters_genericItemsArray:
      in: query
      name: generic_items_array
      required: false
      description: |
        When true, the order's line items are returned as a single
        polymorphic `items` array rather than the typed
        `appointment_items`, `area_booking_items` etc. groupings. Easier to
        iterate from the storefront; less convenient for type-aware
        operator tooling.
      schema:
        type: boolean
        default: false
    orderIntakeFormId:
      in: path
      name: orderIntakeFormId
      required: true
      description: |
        The unique identifier of the `Order` whose intake forms are being
        listed. (The route parameter is named for the resource it surfaces;
        the underlying lookup keys on order/basket ID.)
      schema:
        type: string
        format: object-id
    requestId:
      name: requestId
      in: path
      required: true
      description: |
        The unique identifier of the PMS integration `Request`. PMS
        requests are created when Trybe calls out to an integration (e.g.
        Opera FIAS, Mews); failed ones can be retried via this endpoint.
      schema:
        type: string
        format: object-id
    parameters_practitionerIds:
      in: query
      name: practitioner_ids
      required: true
      description: |
        Comma-separated list of practitioner IDs to compute availability
        for. The calling user must be able to `view` every practitioner;
        a single forbidden practitioner returns `403`.
      schema:
        type: string
        example: 5dcb47800000000000000001,5dcb47800000000000000002
    parameters_dateTimeFrom-2:
      in: query
      name: date_time_from
      required: false
      description: |
        Inclusive start timestamp (`YYYY-MM-DD HH:mm:ss`) to compute
        availability for. Required when `date_from`/`date_to` are not
        supplied. Use this form for sub-day queries.
      schema:
        type: string
    parameters_dateTimeTo-2:
      in: query
      name: date_time_to
      required: false
      description: |
        Exclusive end timestamp. Required when `date_from`/`date_to` are
        not supplied. Must be strictly after `date_time_from`.
      schema:
        type: string
    queuedJobId:
      name: queuedJobId
      in: path
      required: true
      description: The unique identifier of the queued job.
      schema:
        type: string
        format: object-id
    roomReservationTypeId:
      name: roomReservationTypeId
      in: path
      required: true
      description: |
        The unique identifier of the `TableReservationType`. Despite the
        `room-reservation-types` URL alias used here for legacy reasons,
        the underlying resource type is `TableReservationType`.
      schema:
        type: string
        format: object-id
    parameters_roomIds-2:
      in: query
      name: room_ids
      required: true
      description: |
        Comma-separated list of room IDs to compute availability for. The
        calling user must be able to `view` every room; a single forbidden
        room returns `403`.
      schema:
        type: string
        example: 5dcb47800000000000000001,5dcb47800000000000000002
    parameters_brandId-2:
      in: path
      name: brandId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        Stable identifier for the `Brand`. Brands are the top-level
        container for customers, memberships, gift vouchers and email
        templates — every site belongs to exactly one brand. The caller
        must have access to the brand to read or modify it.
    customerIdsQuery:
      in: query
      name: customer_id
      schema:
        type: array
        items:
          type: string
      explode: false
      description: The customer IDs to filter check-ins by
    siteIdQuery:
      in: query
      name: site_id
      schema:
        type: string
      description: The site ID to filter check-ins by
    parameters_dateFromQuery:
      in: query
      name: date_from
      schema:
        type: string
      description: Filter check-ins and check-outs that happened on or after the given datetime.
    parameters_dateToQuery:
      in: query
      name: date_to
      schema:
        type: string
      description: Filter check-ins and check-outs that happened on or before the given datetime.
    checkedInAtFromQuery:
      in: query
      name: checked_in_at_from
      schema:
        type: string
      description: Filter check-ins that happened on or after the given datetime.
    checkedInAtToQuery:
      in: query
      name: checked_in_at_to
      schema:
        type: string
      description: Filter check-ins that happened on or before the given datetime.
    methodIdQuery:
      in: query
      name: method_id
      schema:
        type: string
      description: Filter check-ins that were created by the given method ID.
    methodTypeQuery:
      in: query
      name: method_type
      schema:
        type: string
        enum:
          - gantner
      description: Filter check-ins that were created by the given method type.
    customerIdQuery:
      in: query
      name: customer_id
      schema:
        type: string
      description: The customer ID to filter check-ins by.
    contraindicationIdPath:
      name: contraindicationId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the contraindication this operation is scoped to.
    addressIdPath:
      name: addressId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the address this operation is scoped to.
    barcodeIdPath:
      name: barcodeId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the associated barcode this operation is scoped to.
    redeemedQuery:
      in: query
      name: redeemed
      required: false
      schema:
        type: boolean
      description: Whether to include redeemed credits
    expiredQuery:
      in: query
      name: expired
      required: false
      schema:
        type: boolean
      description: Whether to include expired credits
    revokedQuery:
      in: query
      name: revoked
      required: false
      schema:
        type: boolean
      description: Whether to include revoked credits
    multiUseQuery:
      in: query
      name: multi_use
      required: false
      schema:
        type: boolean
      description: Filter on credits that are multi-use or single-use
    creditIdPath:
      name: creditId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the customer credit this operation is scoped to.
    marketingPreferenceIdPath:
      name: marketingPreferenceId
      in: path
      required: true
      schema:
        type: string
      description: The unique identifier of the marketing preference this operation is scoped to.
    noteIdPath:
      name: noteId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the customer note this operation is scoped to.
    parameters_code-6:
      in: path
      name: code
      required: true
      schema:
        type: string
      description: |
        The barcode to search for. This could either be the ID of the customer or an associated barcode.
    parameters_siteIdQuery:
      in: query
      name: site_id
      required: true
      schema:
        type: string
      description: The site ID to scope the search to.
    updated_at_from:
      in: query
      name: updated_at_from
      schema:
        type: string
      description: Filters customers that were updated on or after the given date.
    updated_at_to:
      in: query
      name: updated_at_to
      schema:
        type: string
      description: Filters customers that were updated on or before the given date.
    labelIdPath:
      name: labelId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the label this operation is scoped to.
    membershipChargeId:
      in: path
      name: membershipChargeId
      required: true
      description: The ID of the membership charge
      schema:
        type: string
        format: uuid
    membershipRateId:
      in: path
      name: membershipRateId
      required: true
      description: The ID of the membership rate
      schema:
        type: string
        format: uuid
    parameters_rateId:
      in: path
      name: rateId
      required: true
      description: The ID of the membership rate
      schema:
        type: string
        format: uuid
    totalsStartDate:
      in: query
      name: start_date
      description: The date the membership will start
      schema:
        type: string
        format: date
        example: '2021-02-19'
    totalsEndDate:
      in: query
      name: end_date
      description: The date the membership will end
      schema:
        type: string
        format: date
        example: '2022-02-19'
    totalsSource:
      in: query
      name: source
      description: The source of the membership
      schema:
        type: string
        example: app
    acceptLanguage:
      in: header
      name: Accept-Language
      description: The language to use for the response.
      schema:
        type: string
        example: en
    memberCustomerId:
      in: path
      name: customerId
      description: The ID of the customer to act on within the membership
      required: true
      schema:
        type: string
        format: uuid
    redeemed:
      in: query
      name: redeemed
      required: false
      schema:
        type: boolean
      description: Whether to include redeemed credits
    expired:
      in: query
      name: expired
      required: false
      schema:
        type: boolean
      description: Whether to include expired credits
    parameters_marketingPreferenceIdPath:
      in: path
      name: marketingPreferenceId
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the marketing preference this operation is scoped to.
    parameters_siteId-74:
      in: query
      name: site_id
      description: The site ID to filter subscriptions by
      schema:
        type: string
    subscriptionId:
      in: path
      name: subscriptionId
      required: true
      description: The ID of the subscription
      schema:
        type: string
    paymentMethodId:
      in: path
      name: paymentMethodId
      required: true
      description: The ID of the payment method
      schema:
        type: string
    signupTokenId:
      in: path
      name: signupTokenId
      required: true
      description: The ID of the signup token
      schema:
        type: string
        format: uuid
    parameters_deviceId:
      in: query
      name: device_id
      description: The ID of the Gantner device to filter logs by
      schema:
        type: string
    logType:
      in: query
      name: type
      description: The type of log to filter by
      schema:
        type: string
    entryRuleId:
      in: path
      name: entryRuleId
      required: true
      description: The ID of the Gantner device entry rule
      schema:
        type: string
        format: uuid
    requiredSiteIdQuery:
      in: query
      name: site_id
      required: true
      schema:
        type: string
      description: |
        Scope the notifications to a single `Site`. When not specified
        the platform falls back to the user's default site. Use this
        when a user works across multiple sites and you want their
        site-specific inbox.
      example: beddda88-947d-4bd8-8f0c-828b187f93c3
    locationId:
      in: path
      name: locationId
      required: true
      schema:
        type: string
        format: uuid
      description: The ID of the inventory location.
    supplierProductId:
      in: path
      name: supplierProductId
      description: The ID of the supplier-product association.
      required: true
      schema:
        type: string
        format: uuid
    parameters_queuedJobId:
      in: path
      name: queuedJobId
      required: true
      schema:
        type: string
      description: The ID of the queued job.
      example: 5ed2b4ea39e32a634f12521f
    parameters_categoryIds-6:
      in: query
      name: category_ids
      description: A comma-separated list of category IDs to filter the items by.
      explode: false
      style: form
      schema:
        type: array
        items:
          type: string
    parameters_supplierIds-3:
      in: query
      name: supplier_ids
      description: A comma-separated list of supplier IDs to filter the items by.
      explode: false
      style: form
      schema:
        type: array
        items:
          type: string
    parameters_brandIds-6:
      in: query
      name: brand_ids
      description: A comma-separated list of brand IDs to filter the items by.
      explode: false
      style: form
      schema:
        type: array
        items:
          type: string
    parameters_query-20:
      in: query
      name: query
      schema:
        type: string
      description: A query to filter the products on. This searches the product name.
      example: Jane
    parameters_status-15:
      in: query
      name: status
      schema:
        type: string
        enum:
          - all
          - uncounted
          - counted
      description: The status to filter the stock take items on.
    featureFlagKey:
      in: path
      name: featureFlagKey
      required: true
      description: |
        The flag's stable key — a kebab-case identifier such as
        `kiosk-self-checkin` or `intake-forms-v2`. Keys are defined at the
        application layer, not in this API; ask backend for the
        authoritative list before depending on a new one.
      schema:
        type: string
    parameters_requiredSiteIdQuery:
      in: query
      name: site_id
      required: true
      schema:
        type: string
        format: uuid
      description: |
        Scope the notifications to a single `Site`. When not specified
        the platform falls back to the user's default site. Use this
        when a user works across multiple sites and you want their
        site-specific inbox.
      example: beddda88-947d-4bd8-8f0c-828b187f93c3
    readQuery:
      in: query
      name: read
      description: Filter results by read state. When `true`, only previously-read notifications are returned; when `false`, only unread.
      schema:
        type: boolean
      example: true
    typeQuery:
      in: query
      name: type
      schema:
        type: array
        items:
          type: string
      explode: false
      style: form
      description: A list of notification types to filter by, e.g. `guestline_order_created`.
    notificationId:
      in: path
      name: notificationId
      required: true
      schema:
        type: string
        format: uuid
      description: |
        Stable identifier for the in-app notification. Only the user
        the notification was delivered to can read, acknowledge or
        mark it (un)read; requests from other users return `404`.
      example: beddda88-947d-4bd8-8f0c-828b187f93c3
    tokenId:
      in: path
      name: tokenId
      required: true
      schema:
        type: string
      description: |
        Stable identifier for the personal-access token. Only the user
        who owns the token (or an admin acting on their behalf) can read
        or revoke it. Use this to scope `deletePersonalAccessToken` calls
        to a specific token.
      example: 636314fa433bf39aeae79b031e5218b999968174ccabcd37a40a8a04614e3fd6a21f08385fee7d65
    parameters_siteIdQuery-2:
      in: query
      name: site_id
      required: true
      schema:
        type: string
        format: uuid
      description: The site id the action is being performed on.
      example: 00000000-0000-0000-0000-111111111111
    parameters_orderId-4:
      in: path
      name: orderId
      required: true
      description: The ID of the order.
      schema:
        type: string
        format: object-id
    parameters_guestId-2:
      in: path
      name: guestId
      required: true
      description: The ID of the guest within the order.
      schema:
        type: string
        format: object-id
    parameters_siteIdPath:
      name: siteId
      in: path
      required: true
      description: The ID of the site to check package availability at.
      schema:
        type: string
        format: uuid
    parameters_optionId:
      name: optionId
      in: path
      required: true
      description: |
        The unique identifier of the `PackageItemChoiceOption` — one of
        the offerings exposed by the parent `PackageItemChoice` as a
        pickable slot in the package.
      schema:
        type: string
        format: object-id
    parameters_code-7:
      in: path
      name: code
      required: true
      schema:
        type: string
      description: The barcode to search for.
    siteIdOptional:
      in: query
      name: site_id
      required: false
      description: |
        Scope the deposit-ledger report to a single `Site`. Omit to
        include every site the caller has reporting access to. Useful
        when the report is being run on behalf of a multi-site brand.
      schema:
        type: string
        format: uuid
        example: 5dcb47800000000000000010
    bookingId:
      in: path
      name: bookingId
      required: true
      description: The ID of the `SessionBooking`.
      schema:
        type: string
        format: object-id
      example: 5dcb47800000000000000000
    parameters_siteIdQuery-3:
      in: query
      name: site_id
      required: true
      description: The site to scope the search to.
      schema:
        type: string
        format: uuid
    parameters_customerIdQuery:
      in: query
      name: customer_id
      required: false
      description: Limit to intake forms filled out for this customer.
      schema:
        type: string
        format: uuid
    basketIdQuery:
      in: query
      name: basket_id
      required: false
      description: Limit to intake forms relating to this basket.
      schema:
        type: string
        format: uuid
    parameters_typeQuery:
      in: query
      name: type
      required: false
      description: |
        Limit to intake forms of the given type (e.g. `mandatory`).
      schema:
        type: string
      example: mandatory
    parameters_basketId:
      in: query
      name: basket_id
      required: true
      description: The basket to look up intake forms for.
      schema:
        type: string
    parameters_siteId-75:
      in: query
      name: site_id
      required: true
      description: The site the basket belongs to.
      schema:
        type: string
    visitIntakeFormId:
      in: path
      name: visitIntakeFormId
      required: true
      description: The ID of the `VisitIntakeForm`.
      schema:
        type: string
        format: object-id
      example: 634d6e9f413841226003acc2
    parameters_voucherCode:
      in: path
      name: voucherCode
      required: true
      description: The voucher code to look up.
      schema:
        type: string
      example: ABC123XYZ
    voucherPurchaseId:
      in: path
      name: voucherPurchaseId
      required: true
      description: The ID of the `VoucherPurchase`.
      schema:
        type: string
        format: object-id
      example: 5dcb47800000000000000000
    parameters_siteId-76:
      in: query
      name: site_id
      description: The site to return yield insights for.
      required: true
      schema:
        type: string
        format: uuid
    yieldInsightsPeriod:
      in: query
      name: period
      required: false
      description: |
        The reporting period to calculate results over, ending now.
        Defaults to `last_30_days`. Shared by the yield insights endpoints
        so a dashboard can request every panel over the same window.
      schema:
        type: string
        enum:
          - last_30_days
          - last_60_days
          - last_90_days
        default: last_30_days
        example: last_30_days
    yieldInsightsHeatmapType:
      in: query
      name: type
      required: false
      description: |
        Which offerings the averages cover. Defaults to `appointments`.

        Rooms and bookable areas are not a type here: they are returned one row
        per resource by
        [room and area occupancy](/endpoints/YieldInsights#getYieldInsightsRoomOccupancy).
      schema:
        type: string
        enum:
          - appointments
          - sessions
        default: appointments
    parameters_siteId-77:
      in: query
      name: site_id
      description: The site whose yield rules to list.
      required: true
      schema:
        type: string
        format: uuid
    parameters_offeringType-9:
      in: query
      name: offering_type
      description: |
        Narrow the list to one offering, alongside `offering_id`. Both are needed
        together, since an ID alone does not identify the kind of offering.
      required: false
      schema:
        $ref: '#/components/schemas/offeringType'
    parameters_offeringId-9:
      in: query
      name: offering_id
      description: |
        Narrow the list to one offering, alongside `offering_type`.
      required: false
      schema:
        type: string
        format: uuid
    createdBatchId:
      in: query
      name: created_batch_id
      description: |
        Narrow the list to the rules created by one request. Used to follow a create
        that was answered with `202` and handed off to a background job.
      required: false
      schema:
        type: string
        format: uuid
    yieldRule:
      in: path
      name: yieldRule
      description: The ID of the yield rule.
      required: true
      schema:
        type: string
        format: uuid
    guestlineRef:
      name: guestlineRef
      in: path
      required: true
      schema:
        type: string
      description: |
        The Guestline PMS reservation reference to look up. Trybe stores
        this on the `Customer` record as `guestline_ref` when the customer
        was provisioned from a Guestline-integrated property's reservation
        feed. Matches are exact (case-sensitive).
    parameters_membershipId:
      in: query
      name: membership_id
      schema:
        type: string
      description: Filters charges by the membership ID
    parameters_status-16:
      in: query
      name: status
      schema:
        type: string
        example: processing
      description: Filters charges by the status
    billingPeriodFromStart:
      in: query
      name: billing_period_from_start
      schema:
        type: string
        format: date
        example: '2020-01-01'
      description: Filters charges to those with a 'billing period from' on or after the specified date
    billingPeriodFromEnd:
      in: query
      name: billing_period_from_end
      schema:
        type: string
        format: date
        example: '2020-01-01'
      description: Filters charges to those with a 'billing period to' on or before the specified date
    createdAtStart:
      in: query
      name: created_at_start
      schema:
        type: string
        format: date
        example: '2020-01-01'
      description: Filters charges to those with a 'created at' on or after the specified date
    createdAtEnd:
      in: query
      name: created_at_end
      schema:
        type: string
        format: date
        example: '2020-01-01'
      description: Filters charges to those with a 'created at' on or before the specified date
    amountFrom:
      in: query
      name: amount_from
      schema:
        type: number
        format: integer
      example: 1000
      description: Filters charges to those with an amount greater than or equal to the specified value
    amountTo:
      in: query
      name: amount_to
      schema:
        type: number
        format: integer
      example: 1000
      description: Filters charges to those with an amount less than or equal to the specified value
    parameters_processor-2:
      in: query
      name: processor
      schema:
        type: string
        example: stripe
      description: Filters charges by the processor
    parameters_email-4:
      in: query
      name: email
      required: false
      schema:
        type: boolean
      description: |
        When `true`, the completed CSV is emailed to the requesting user
        once the job finishes (in addition to being available via the
        queued-job download URL). Defaults to `false`.
    endDate:
      in: query
      name: end_date
      required: false
      schema:
        type: string
        format: date
      example: '2026-12-31'
      description: |
        The proposed new end date for the membership, in `YYYY-MM-DD`
        format. Pass an empty value to preview removing the end date
        entirely (converting a fixed-term membership to open-ended).
        Must be strictly after the membership's `start_date`.
    token:
      in: query
      name: token
      required: false
      schema:
        type: string
        format: uuid
      description: |
        Optional `MembershipSignupToken` ID. When present, the response is
        narrowed to the membership type and / or rate that the token is
        scoped to, and the `customer_details` field is populated with any
        pre-filled name / email / phone the token carries — typically used
        to deep-link a personalised signup URL from a marketing email.
    parameters_organisationId-4:
      in: query
      name: organisation_id
      required: true
      schema:
        type: string
        format: uuid
      description: |
        The organisation whose public marketing preferences to return.
        Required — public callers must scope the lookup to a specific
        organisation.
    parameters_site_id-3:
      in: query
      name: site_id
      required: true
      schema:
        type: string
        format: uuid
      description: Filters segments that belong to the given site ID.
    parameters_query-21:
      in: query
      name: query
      schema:
        type: string
      description: Filters segments whose name contains the given value.
      example: Premium
    customerSegmentId:
      in: path
      name: customerSegmentId
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the customer segment.
    parameters_query-22:
      in: query
      name: query
      schema:
        type: string
      description: Filters members whose customer name or email contains the given value.
      example: jane
    subscribed:
      in: query
      name: subscribed
      schema:
        type: boolean
      description: When `true`, only subscribed members are returned. When `false`, only unsubscribed members are returned.
    memberId:
      in: path
      name: memberId
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the segment membership record.
    parameters_site_id-4:
      in: query
      name: site_id
      required: true
      schema:
        type: string
        format: uuid
      description: Filters campaigns that belong to the given site ID.
    parameters_query-23:
      in: query
      name: query
      schema:
        type: string
      description: Filters campaigns whose name contains the given value.
      example: Summer
    parameters_sort-6:
      in: query
      name: sort
      schema:
        type: string
        enum:
          - created_at
          - '-created_at'
          - updated_at
          - '-updated_at'
          - scheduled_at
          - '-scheduled_at'
          - sent_at
          - '-sent_at'
      description: |
        The field to sort results by. Prefix with `-` for descending order.
        Defaults to `-created_at`.
    scheduled_at_from:
      in: query
      name: scheduled_at_from
      schema:
        type: string
        format: date-time
      description: Filters campaigns with a `scheduled_at` on or after the given datetime.
    scheduled_at_to:
      in: query
      name: scheduled_at_to
      schema:
        type: string
        format: date-time
      description: Filters campaigns with a `scheduled_at` on or before the given datetime.
    sent_at_from:
      in: query
      name: sent_at_from
      schema:
        type: string
        format: date-time
      description: Filters campaigns with a `sent_at` on or after the given datetime.
    sent_at_to:
      in: query
      name: sent_at_to
      schema:
        type: string
        format: date-time
      description: Filters campaigns with a `sent_at` on or before the given datetime.
    campaignId:
      in: path
      name: campaignId
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the campaign.
    parameters_locale:
      in: query
      name: locale
      schema:
        type: string
      description: Filters content records for the given locale code.
      example: en-GB
    parameters_query-24:
      in: query
      name: query
      schema:
        type: string
      description: Filters content records whose subject or body contains the given value.
      example: summer
    contentId:
      in: path
      name: contentId
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the campaign content.
    parameters_query-25:
      in: query
      name: query
      schema:
        type: string
      description: Filters sends whose recipient customer name or email contains the given value.
      example: jane
    sent:
      in: query
      name: sent
      schema:
        type: boolean
      description: When `true`, only sends that have been sent are returned. When `false`, only unsent sends are returned.
    failed:
      in: query
      name: failed
      schema:
        type: boolean
      description: When `true`, only sends that have failed are returned. When `false`, only non-failed sends are returned.
    bounced:
      in: query
      name: bounced
      schema:
        type: boolean
      description: When `true`, only sends that have bounced are returned. When `false`, only non-bounced sends are returned.
    sendId:
      in: path
      name: sendId
      required: true
      schema:
        type: string
        format: uuid
      description: The unique identifier of the campaign send.
  schemas:
    PaginationLinks:
      type: object
      description: Hypermedia navigation links for paging through a list response. Each property is a fully-qualified URL that preserves the original query string (filters, sort, page size) and only swaps the `page` parameter. `next` and `prev` are `null` at the ends of the result set; `first` and `last` are always present.
      title: PaginationLinks
      additionalProperties: false
      properties:
        first:
          type: string
          description: The url of the first page for the paginated results set
          example: http://example.com?page=1
        next:
          type: string
          description: The url of the next page for the paginated results set
          example: https://example.com?page=3
          nullable: true
        prev:
          type: string
          description: The url of the previous page for the paginated results set
          example: https://example.com?page=1
          nullable: true
        last:
          type: string
          description: The url of the last page for the paginated results set
          example: https://example.com?page=4
      required:
        - first
        - next
        - prev
        - last
    PaginationMeta:
      type: object
      title: PaginationMeta
      description: Counts and positional information for the current page of a list response. Use `current_page` and `last_page` to drive pagination UI, `total` for result counts, and `per_page` to confirm the page size the server actually applied (which may differ from the requested value when capped).
      additionalProperties: false
      properties:
        from:
          type: integer
          description: The item number from which this results set starts from
          example: 1
        to:
          type: integer
          description: The item number from which this results set ends at
          example: 2
        total:
          type: integer
          description: The total number of results
          example: 2
        current_page:
          type: integer
          description: The current page number
          example: 1
        last_page:
          type: integer
          description: The page number of the last result set
          example: 2
        per_page:
          type: integer
          description: The number of results per page
          example: 15
        path:
          type: string
          description: The path of this api request
          example: http://example.com/api
      required:
        - from
        - to
        - total
        - current_page
        - last_page
        - per_page
        - path
    Pagination:
      title: Pagination
      description: |
        Paginated envelope mixin. `allOf` this into any list response that wraps
        its `data` array with `meta` + `links`; the concrete schema keeps its own
        title so the SDK surface is unchanged, while the `meta` / `links` shape
        is sourced from a single definition.
      type: object
      additionalProperties: false
      properties:
        links:
          $ref: '#/components/schemas/PaginationLinks'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
      required:
        - links
        - meta
    ApiUser:
      title: ApiUser
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the user
          format: uuid
        name:
          type: string
          description: The user's name
          example: Internal
        organisation_name:
          type: string
          description: The name of the organisation that this user belongs to
          example: Trybe Spa
        organisation_id:
          type: string
          description: The ID of the organisation that this user belongs to
          format: uuid
        site_ids:
          type: array
          description: The IDs of the sites that this user belongs to
          items:
            type: string
            format: uuid
        status:
          type: string
          description: The status of the user
          example: active
        created_at:
          type: string
          format: date-time
          description: The date and time the user was created
          example: '2020-01-01T00:00:00.000Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time the user was last updated
          example: '2020-01-01T00:00:00.000Z'
      required:
        - id
        - name
        - organisation_id
        - site_ids
        - status
        - created_at
        - updated_at
    DataEnvelope:
      title: DataEnvelope
      description: |
        Single-item envelope mixin. `allOf` this into any show response that wraps
        its `data` payload in an outer object; the concrete schema (e.g. `ShowUser`)
        adds its own `data` property with the appropriate `$ref` and keeps its own
        title so the SDK surface is unchanged.
      type: object
      additionalProperties: false
    ApiUserWithToken:
      title: ApiUserWithToken
      description: |
        An API user augmented with a freshly-minted personal access
        token. Only returned by `createApiUser`; the token is not
        stored in a retrievable form and cannot be looked up later.
      allOf:
        - $ref: '#/components/schemas/ApiUser'
        - type: object
          title: ApiUserTokenProperties
          additionalProperties: false
          required:
            - token
          properties:
            token:
              type: string
              description: |
                Bearer token to authenticate as the new API user.
                Returned once on create; store it securely. If lost,
                generate a new one via the admin API-user
                regenerate-token endpoint.
              example: eyABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910ABCDEFGHIJKLMNOPQRSTUVWXYZx.eyABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910ABCDEFGHIJKLMNOPQRSTUVWXYZx.ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910ABCDEFGHIJKLMNOPQRSTUVWXYZ
    SupportedLocale:
      type: object
      title: SupportedLocale
      additionalProperties: false
      properties:
        code:
          type: string
          description: The locale code
          example: en
        name:
          type: string
          description: The locale name, in the language of the locale
          example: English
        emoji:
          type: string
          description: An emoji representing the locale
          example: 🇬🇧
      required:
        - code
        - name
        - emoji
    SupportedCurrency:
      type: object
      title: SupportedCurrency
      additionalProperties: false
      required:
        - code
      properties:
        code:
          type: string
          description: The currency code
          example: GBP
    SupportedTimezone:
      type: object
      title: SupportedTimezone
      additionalProperties: false
      required:
        - code
      properties:
        code:
          type: string
          description: The timezone code
          example: Europe/Paris
    OutboundIp:
      type: string
      format: ip
      description: An outbound IP address used by the platform
      example: 63.34.76.240
    Site:
      type: object
      title: Site
      description: A physical or virtual venue under a `Brand` — typically a single spa, club, or location. Sites own their own offerings, sessions, pricing and staff, and are the unit at which API keys are scoped. A user must be granted access to a site individually before they can act on its data.
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the site
        billing_customer_id:
          type: string
        brand_id:
          type: string
          format: uuid
          description: The ID of the `Brand` the `Site` belongs to.
        brand_name:
          type: string
          description: The name of the `Brand` the `Site` belongs to.
        country_code:
          type: string
          description: The country code of the site
          example: GB
          nullable: true
        created_at:
          type: string
          format: date-time
          description: The date and time that the site was created
        onboarding_completed_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time that the site's onboarding was completed
        currency:
          type: string
          description: The currency of the site. See [Supported Currencies](/endpoints/Meta#listMetaSupportedCurrencies) for a list of supported currencies.
          example: GBP
        external_id:
          type: string
          description: |
            An external ID for the site
            This can be used to link the site to an external system.
          nullable: true
          example: ext-site-london-bridge
        frontend_subdomain:
          type: string
          description: The subdomain of the site's frontend
          example: palmtreespa
        is_read_only:
          type: boolean
          description: Are billing details read-only.
        locale:
          type: string
          description: The locale of the site. See [Supported Locales](/endpoints/Meta#listMetaSupportedLocales) for a list of supported locales.
          example: en
        name:
          type: string
          description: |
            Display name of the site. Shown to customers in the storefront,
            in the admin UI, on receipts, and on communications. Trimmed;
            1-120 characters, must not contain HTML.
          example: Palm Tree Spa
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation that the site belongs to
        organisation_name:
          type: string
          description: The name of the organisation that the site belongs to
          example: Palm Tree Holdings Ltd.
        property_type:
          type: string
          description: The type of property the site is.
          enum:
            - Spa & Leisure Hotel
            - Spa Hotel
            - Spa Hotel & Golf
            - Standalone Leisure
            - Standalone Spa
            - Other
          default: Spa & Leisure Hotel
          example: Spa & Leisure Hotel
        timezone:
          type: string
          nullable: true
          description: The site's local timezone as an IANA zone identifier (e.g. `Europe/London`, `America/New_York`). All schedule, opening hours and reporting figures are interpreted in this zone, and the value is used to convert UTC timestamps in API responses into local times for display.
          example: Europe/London
      required:
        - id
        - billing_customer_id
        - brand_id
        - brand_name
        - country_code
        - created_at
        - currency
        - external_id
        - frontend_subdomain
        - is_read_only
        - locale
        - name
        - onboarding_completed_at
        - organisation_id
        - organisation_name
        - property_type
        - timezone
    name:
      type: string
      description: |
        Display name of the site. Shown to customers in the storefront,
        in the admin UI, on receipts, and on communications. Trimmed;
        1-120 characters, must not contain HTML.
      example: Palm Tree Spa
    locale:
      type: string
      description: The locale of the site. See [Supported Locales](/endpoints/Meta#listMetaSupportedLocales) for a list of supported locales.
      example: en
    currency:
      type: string
      description: The currency of the site. See [Supported Currencies](/endpoints/Meta#listMetaSupportedCurrencies) for a list of supported currencies.
      example: GBP
    timezone:
      type: string
      nullable: true
      description: The site's local timezone as an IANA zone identifier (e.g. `Europe/London`, `America/New_York`). All schedule, opening hours and reporting figures are interpreted in this zone, and the value is used to convert UTC timestamps in API responses into local times for display.
      example: Europe/London
    property_type:
      type: string
      description: The type of property the site is.
      enum:
        - Spa & Leisure Hotel
        - Spa Hotel
        - Spa Hotel & Golf
        - Standalone Leisure
        - Standalone Spa
        - Other
      default: Spa & Leisure Hotel
      example: Spa & Leisure Hotel
    UpdateSite:
      title: UpdateSite
      type: object
      description: |
        The fields to update on a `Site`.
      additionalProperties: false
      properties:
        name:
          $ref: '#/components/schemas/name'
        locale:
          $ref: '#/components/schemas/locale'
        currency:
          $ref: '#/components/schemas/currency'
        timezone:
          $ref: '#/components/schemas/timezone'
        property_type:
          $ref: '#/components/schemas/property_type'
        logo_media_id:
          type: string
          description: |
            The media ID of the Site's logo.

            To obtain a Media ID, use the [`createMedia`](/endpoints/Media/#createMedia) endpoint to upload your media.
          format: uuid
          nullable: true
        external_id:
          type: string
          description: |
            An external ID for the site
            This can be used to link the site to an external system.
          nullable: true
          example: ext-site-london-bridge
        country_code:
          type: string
          description: The country code of the site
          example: GB
          nullable: true
    Media:
      type: object
      title: Media
      additionalProperties: false
      properties:
        id:
          type: string
          description: |
            Unique identifier of the uploaded media item, returned from
            `createMedia`. Pass this ID into any field that accepts a
            media reference (logos, hero images, product images, etc.).
          format: uuid
        file_name:
          type: string
          description: |
            Original filename of the uploaded asset, preserved as
            provided at upload time. Used for display in the media
            library and as a hint when serving downloads.
          example: super-cool-photo.jpg
        mime_type:
          type: string
          description: The mime type of the media item.
          example: image/jpeg
        original_url:
          type: string
          description: The url of the media resource.
          example: https://example.com/media/super-cool-photo.jpg
        size:
          type: integer
          description: The size of the media item in bytes.
          example: 84256
        url:
          type: string
          description: The url of the converted media resource.
          example: https://example.com/media/super-cool-photo-thumbnail@2x.jpg
      required:
        - id
        - file_name
        - mime_type
        - original_url
        - size
        - url
    BookableAreaSummary:
      title: BookableAreaSummary
      description: Summary details of a bookable area.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the bookable area.
          type: string
          format: mongo-id
        name:
          description: The name of the bookable area.
          type: string
          example: Hot Tub 1
      required:
        - id
        - name
    UserSummary:
      title: ShopUserSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the user.
        avatar:
          $ref: '#/components/schemas/Media'
        email:
          type: string
          format: email
        first_name:
          type: string
          example: Jane
        full_name:
          type: string
          example: Jane Smith
        last_name:
          type: string
          example: Smith
      required:
        - id
        - email
        - first_name
        - full_name
        - last_name
    CalendarBlockedTimeDetailsResource:
      title: CalendarBlockedTimeDetailsResource
      type: object
      additionalProperties: false
      required:
        - color
        - label
        - notes
        - type
        - created_at
        - created_by
      properties:
        color:
          type: string
          description: A hex code that the blocked time should be displayed as on the calendar.
          example: '#f55656'
        label:
          type: string
          description: A label that summarises the blocked time.
          example: Lunch
        notes:
          type: string
          description: Any notes that give more detail on the blocked time.
          example: Can be rearranged if required.
        type:
          type: string
          description: The type code for the blocked time.
          example: break
        created_at:
          type: string
          format: date-time
          example: '2019-06-15T12:00:00+01:00'
          description: The date and time the blocked time was created.
        created_by:
          $ref: '#/components/schemas/UserSummary'
    GuestSummary:
      title: GuestSummary
      description: Details of a guest who is part of an order.
      type: object
      additionalProperties: false
      required:
        - id
        - name
        - checked_in_at
      properties:
        id:
          description: The ID of the guest.
          type: string
          format: mongo-id
        customer_id:
          description: The ID of the customer this guest relates to.
          type: string
          format: mongo-id
          nullable: true
        name:
          description: The guest's full name.
          type: string
          example: Jane Smith
        checked_in_at:
          description: The date and time the guest checked in.
          type: string
          format: date-time
          nullable: true
          example: '2025-10-01T12:00:00+00:00'
    id:
      type: string
      description: The ID of the customer.
      format: uuid
    email:
      type: string
      description: |
        The email address of the customer.

        The case of the email address is not preserved, so you'll always see this in lowercase.
      example: janedoe@example.com
      nullable: true
    first_name:
      type: string
      description: The first name of the customer.
      nullable: true
      example: Jane
    full_name:
      type: string
      description: The customer's full name
      nullable: true
      example: Jane Doe
    Label:
      title: ShopCustomerLabel
      type: object
      additionalProperties: false
      required:
        - id
        - color
        - name
      properties:
        id:
          type: string
        color:
          type: string
          nullable: true
        name:
          type: string
    last_name:
      type: string
      description: The last name of the customer.
      nullable: true
      example: Doe
    phone:
      type: string
      description: The customer's phone number in E.164 format, or `null` if not provided.
      nullable: true
      example: '+447900000000'
    CustomerSummary:
      title: ShopCustomerSummary
      description: A summary of the `Customer` this order belongs to.
      type: object
      additionalProperties: false
      required:
        - id
        - email
        - first_name
        - full_name
        - labels
        - last_name
        - phone
      properties:
        id:
          $ref: '#/components/schemas/id'
        email:
          $ref: '#/components/schemas/email'
        first_name:
          $ref: '#/components/schemas/first_name'
        full_name:
          $ref: '#/components/schemas/full_name'
        labels:
          type: array
          items:
            $ref: '#/components/schemas/Label'
        last_name:
          $ref: '#/components/schemas/last_name'
        phone:
          $ref: '#/components/schemas/phone'
    schemas_Label:
      title: OrderLabel
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the label.
          type: string
          format: object-id
        color:
          description: The color of the label.
          type: string
          example: '#FF0000'
        name:
          description: The name of the label.
          type: string
          example: VIP
        order_id:
          type: string
          format: object-id
      required:
        - id
        - color
        - name
        - order_id
    OrderNote:
      title: OrderNote
      description: A note relating to an order.
      type: object
      additionalProperties: false
      required:
        - id
        - content
      properties:
        id:
          type: string
          example: 5ed2b95f72823c4f98419f19
        content:
          type: string
          description: The contents of the note.
          example: Requested a double treatment room.
        order_id:
          type: string
          description: The order this note belongs too
          example: 5ed2b95f72823c4f98419f20
        created_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
          description: The date and time the note was created.
        created_by:
          title: OrderNoteCreatedBy
          type: object
          additionalProperties: false
          required:
            - id
            - name
          properties:
            id:
              type: string
              description: The ID of the user who added the note.
              example: 5ed2b95f72823c4f98419f20
            name:
              type: string
              description: The name of the user who added the note.
              example: Jane Smith
        created_by_id:
          type: string
          description: The ID of the user who added the note.
          example: 5ed2b95f72823c4f98419f20
    PaymentTotals:
      title: OrderPaymentTotals
      type: object
      additionalProperties: false
      properties:
        chargeable:
          description: The total of payments that are ready to be charged when required.
          type: integer
          example: 500
        missing:
          description: |
            The balance of payments still needing to be added to the order, equal to the total
            cost of the order minus any paid, pending and chargeable payments.
          type: integer
          example: 1000
        paid:
          description: The total of payments in a paid status.
          type: integer
          example: 750
        pending:
          description: The total of payments that are still processing.
          type: integer
          example: 250
        provided:
          description: |
            The total of payments that have been added to the order, equal to the total
            of all paid, pending and chargeable payments.
          type: integer
          example: 1500
        unpaid:
          description: |
            The balance of payments that still need to be paid, equal to the total cost of the
            order minus any paid payments.
          type: integer
          example: 1000
      required:
        - chargeable
        - missing
        - paid
        - pending
        - provided
        - unpaid
    CalendarEventOrderSummary:
      title: CalendarEventOrderSummary
      type: object
      additionalProperties: false
      required:
        - id
        - email
        - first_name
        - has_posting_room
        - is_locked
        - intake_form_required
        - intake_forms_completed
        - labels
        - last_name
        - notes
        - order_ref
        - phone
        - special_requests
        - stage
        - status
      properties:
        id:
          type: string
          description: The ID of the order.
          example: 5e9823c217483703da777777
        customer:
          $ref: '#/components/schemas/CustomerSummary'
        email:
          type: string
          description: The email address of the lead booker.
          example: janedoe@example.com
        external_visit_ref:
          type: string
          description: An external visit reference for the order, if set.
          example: RES1234
        first_name:
          type: string
          description: The first name of the lead booker.
          example: Jane
        has_posting_room:
          type: boolean
          description: Whether this order has an attached posting room.
          example: true
        intake_form_required:
          type: boolean
          description: Whether this order requires an intake form to be completed.
          example: true
        intake_forms_completed:
          type: boolean
          description: Whether the required intake form has been completed.
          example: false
        is_locked:
          type: boolean
          description: Whether this order is locked to the current resources (practitioner, room etc)
          example: true
        labels:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Label'
        last_name:
          type: string
          description: The last name of the lead booker.
          example: Doe
        notes:
          type: array
          description: Whether this order has notes added to it.
          items:
            $ref: '#/components/schemas/OrderNote'
        order_ref:
          type: string
          description: The order reference.
          example: TRY00
        payment_totals:
          $ref: '#/components/schemas/PaymentTotals'
        phone:
          type: string
          description: The phone number of the lead booker.
          example: '+447727123456'
        special_requests:
          nullable: true
          type: string
          description: Any special requests from the customer.
          example: I would like the Blue Room please
        stage:
          type: string
          description: The current stage of the order.
          enum:
            - not_arrived
            - arrived
            - in_treatment
            - checked_out
        status:
          type: string
          description: The status of the order.
          example: complete
    CalendarBookingSummaryResource:
      title: CalendarBookingSummaryResource
      type: object
      additionalProperties: false
      required:
        - id
        - booking_type
        - guests
        - order
        - status
      properties:
        id:
          type: string
          description: The ID of the booking
          example: 5e9823c217483703da555555
        booking_type:
          type: string
          description: The type of the booking
          enum:
            - appointment
            - area_booking
            - session_booking
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        order:
          $ref: '#/components/schemas/CalendarEventOrderSummary'
        status:
          type: string
          description: The status of the booking
          example: confirmed
    PractitionerSummary:
      title: PractitionerSummary
      description: The summary of a `Practitioner` object
      type: object
      additionalProperties: false
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the practitioner.
          example: 5dcb47800000000000000000
        name:
          type: string
          description: The full name of the practitioner.
          example: Jane Doe
    RoomSummary:
      title: RoomSummary
      description: The summary of a `Room` object
      type: object
      additionalProperties: false
      required:
        - id
        - capacity
        - name
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the room.
          example: 5dcb47800000000000000000
        capacity:
          type: integer
        name:
          type: string
          description: The name of the room.
    CalendarSessionDetailsResource:
      title: CalendarSessionDetailsResource
      type: object
      additionalProperties: false
      required:
        - capacity
        - num_booked
        - num_waitlisted
        - waitlist_enabled
      properties:
        capacity:
          type: integer
          description: The total capacity of the session.
          example: 20
        num_booked:
          type: integer
          description: The number of guests booked on this session
          example: 10
        num_waitlisted:
          type: integer
          description: The number of guests on the waitlist for this session
          example: 0
        waitlist_enabled:
          type: boolean
          example: true
          description: Whether the waitlist is enabled for this session.
    OrderItemWarning:
      title: OrderItemWarning
      description: A warning relating to an order item, typically flagging configuration issues such as missing or mismatched practitioner/room assignments.
      type: object
      additionalProperties: false
      properties:
        code:
          type: string
          description: A machine-readable code identifying the type of warning.
          example: no_practitioner_assigned
        message:
          type: string
          description: A human-readable message describing the warning.
      required:
        - code
        - message
    CalendarEvent:
      title: CalendarEvent
      description: Properties for an event that should be displayed on the calendar
      type: object
      additionalProperties: false
      required:
        - id
        - areas
        - duration
        - end_time
        - event_type
        - key
        - locked
        - practitioners
        - resource_id
        - rooms
        - start_time
      properties:
        id:
          type: string
          description: The ID of the event
          example: 6220d459e7c1c2f0ff31c3f3
        areas:
          type: array
          items:
            $ref: '#/components/schemas/BookableAreaSummary'
        blocked_time_details:
          type: object
          description: |
            If the event is a blocked time, this property will contain additional details
            about the blocked time.
          $ref: '#/components/schemas/CalendarBlockedTimeDetailsResource'
        bookings:
          type: array
          description: |
            For area bookings, multiple bookings with the same start and end times
            will be collapsed into a single event, and this array will be included
            with a summary of the individual bookings making up the combined event.
          items:
            $ref: '#/components/schemas/CalendarBookingSummaryResource'
        duration:
          type: integer
          description: The duration of the event in minutes, excluding any end buffer.
          example: 60
        end_time:
          type: string
          format: date-time
          description: The end time of the event, including any end buffer.
          example: '2022-03-04T13:15:00+00:00'
        end_buffer:
          type: integer
          description: The end buffer of the event.
        event_type:
          type: string
          description: The type of the event
          enum:
            - appointment
            - area_booking
            - session
            - blocked_time
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        key:
          type: string
          description: If a view type is specified, this value contains a unique key for the event and resource ID.
          example: 6220d459e7c1c2f0ff31c3f3_5dcb47800000000000000010
        locked:
          type: boolean
          description: True if this event is locked to the current resources.
          example: true
        num_overlaps:
          type: integer
          description: |
            If a view type is specified, this represents the number of other events with the
            same resource ID that overlap with the time of this event. This value may be used
            to determine the size of the event on the calendar.
          example: 1
        offering_id:
          type: string
          description: The ID of the offering the event relates to.
          example: 5e9823c217483703da222222
        offering_name:
          type: string
          description: The name of the offering the event relates to.
          example: Alpha Massage
        order:
          type: object
          description: A summary of the order this event relates to, if applicable.
          $ref: '#/components/schemas/CalendarEventOrderSummary'
        overlap_order:
          type: integer
          description: |
            If a view type is specified, this represents the order of this event relative to
            other overlapping events. This value may be used to determine the position of the
            event on the calendar.
        practitioners:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerSummary'
        product_code:
          type: string
          description: The product code of the offering the event relates to.
          example: ULO346
        reserved_until:
          type: string
          format: date-time
          description: The end time of the reservation if this event is reserved.
          example: '2022-03-04T12:00:00+00:00'
        resource_id:
          type: string
          nullable: true
          description: If a view type is specified, this value contains the ID of the single resource for this event object.
          example: 5dcb47800000000000000010
        resource_type:
          type: string
          description: If a view type is specified, this value contains the type of the single resource for this event object.
          example: practitioner
        rooms:
          type: array
          items:
            $ref: '#/components/schemas/RoomSummary'
        session_details:
          type: object
          description: |
            If the event is a session, this property will contain additional details
            about the session.
          $ref: '#/components/schemas/CalendarSessionDetailsResource'
        start_time:
          type: string
          format: date-time
          description: The start time of the event.
          example: '2022-03-04T12:00:00+00:00'
        status:
          type: string
          description: The status of the event, if applicable.
          example: confirmed
        warnings:
          type: array
          nullable: true
          description: |
            A list of warnings relating to this event, if applicable. Only present for
            appointment events.
          items:
            $ref: '#/components/schemas/OrderItemWarning'
    CalendarNote:
      title: CalendarNote
      description: |
        A `CalendarNote` is a free-form, date-scoped annotation that
        surfaces on the operator calendar for a site. Staff use these to
        record context for a particular day — e.g. a public holiday,
        a marketing event, a known understaffed shift, or a VIP
        reservation that everyone should know about.

        Notes are date-bound (one day at a time) and site-scoped; they do
        not affect availability or block bookings.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the note.
          example: 5f1234567890abcdef123456
        site_id:
          type: string
          format: uuid
          description: ID of the site this note is attached to.
          example: 11111111-1111-1111-1111-111111111111
        body:
          type: string
          description: |
            The note text. Plain text only — line breaks are preserved but
            no markdown is rendered.
          example: Public holiday — front desk closes at 16:00.
        date:
          type: string
          format: date
          description: |
            The calendar date the note applies to, in `YYYY-MM-DD` format
            in the site's local timezone.
          example: '2026-05-25'
        created_by_id:
          type: string
          format: uuid
          nullable: true
          description: ID of the user who created the note.
          example: 33333333-3333-3333-3333-333333333333
        created_by:
          type: object
          nullable: true
          description: Summary of the user who created the note, if known.
        updated_by_id:
          type: string
          format: uuid
          nullable: true
          description: ID of the user who last updated the note.
          example: 33333333-3333-3333-3333-333333333333
        updated_by:
          type: object
          nullable: true
          description: |
            Summary of the user who last updated the note, if any
            updates have been made.
        deleted_by_id:
          type: string
          format: uuid
          nullable: true
          description: |
            ID of the user who deleted the note, if it has been soft
            deleted. Usually null on live records.
          example: null
        deleted_by:
          type: object
          nullable: true
          description: |
            Summary of the user who deleted the note, if it has been
            soft deleted.
        created_at:
          type: string
          format: date-time
          description: ISO-8601 timestamp of when the note was created.
          example: '2026-05-23T09:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: ISO-8601 timestamp of when the note was last updated.
          example: '2026-05-23T09:30:00Z'
      required:
        - id
        - site_id
        - body
        - date
        - created_at
        - updated_at
    OfferingType:
      description: Discriminator describing what kind of sellable item an `Offering` represents. The value determines which downstream schema (`Appointment`, `Session`, `Package`, etc.) the offering's `offering_id` resolves against, and which checkout/booking flow applies.
      type: string
      enum:
        - appointment
        - appointment_enquiry
        - area_booking
        - course
        - hotel_room_reservation
        - membership
        - package
        - product
        - session
        - table_reservation
        - voucher
      example: appointment
    AppliedPromoCode:
      title: AppliedPromoCode
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the promo code.
          type: string
          format: object-id
        applied_at:
          description: The date and time the promo code was applied.
          type: string
          format: date-time
          example: '2023-11-15T12:00:00+00:00'
        applied_by:
          description: Information about the user who applied the discount. If this is null, the discount was applied by the customer.
          type: object
          $ref: '#/components/schemas/UserSummary'
        code:
          description: The code of the promo code.
          type: string
          example: FIVEOFF
        discount_total:
          description: The total discount from the applied promo code on the order.
          type: integer
          example: 2000
        is_discount_applied:
          description: Whether the discount from the promo code has been applied to the order.
          type: boolean
          example: true
        percentage:
          description: The percentage discount from the promo code.
          type: integer
          example: 10
      required:
        - id
        - code
        - discount_total
        - is_discount_applied
        - percentage
    BasketCouponSummary:
      title: BasketCouponSummary
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the coupon.
          type: string
          format: object-id
        code:
          description: The code of the coupon.
          type: string
          example: FIVEOFF
        name:
          description: The name of the coupon.
          type: string
          example: April special
        description:
          description: A description of the coupon.
          type: string
          example: Get 10% off all treatments booked in April.
        customer_credit_id:
          description: The customer credit this coupon relates to, if applicable.
          type: string
          format: uuid
      required:
        - id
        - code
        - name
        - description
        - customer_credit_id
    properties_currency:
      description: The ISO-4217 currency code.
      type: string
      example: gbp
    Guest:
      title: Guest
      type: object
      additionalProperties: false
      required:
        - id
        - checked_in_at
        - checked_out_at
        - customer_id
        - first_name
        - intake_form_complete
        - is_lead_booker
        - last_name
        - name
      properties:
        id:
          type: string
          format: object-id
          description: |
            Stable identifier for the guest slot on an order. Used to
            attach intake-form answers, check the guest in or out, and
            link the slot to a `Customer` once one is resolved.
          example: 5dcb47800000000000000000
        checked_in_at:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO-8601 timestamp at which the guest checked in for their
            visit. `null` until check-in happens.
          example: '2025-10-01T12:00:00+00:00'
        checked_out_at:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO-8601 timestamp at which the guest checked out / finished
            their visit. `null` while the visit is still in progress.
          example: '2025-10-01T16:30:00+00:00'
        customer_id:
          type: string
          format: uuid
          nullable: true
          description: |
            The `Customer` the guest slot has been linked to, if any.
            `null` for walk-ins or anonymous guests that haven't been
            matched to a customer record yet.
          example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
        email:
          type: string
          format: email
          nullable: true
          description: |
            Email address captured for this guest, used to send the
            pre-visit intake form and post-visit follow-ups. `null` when
            no email has been supplied for the slot.
          example: jane.doe@example.com
        first_name:
          type: string
          description: The first name of the guest.
          example: Jane
        intake_form_submission_id:
          type: string
          format: object-id
          description: |
            Identifier of the most recent intake-form submission for this
            guest, if one exists. Use this to fetch the submitted answers
            from the guest-intake API.
          example: 5dcb47800000000000000010
        intake_form_complete:
          type: boolean
          description: Whether the intake form for the guest is complete.
        is_lead_booker:
          type: boolean
          description: Whether the guest is the lead booker.
        last_name:
          type: string
          description: The last name of the guest.
          example: Doe
        name:
          type: string
          description: |
            Full display name for the guest — typically `first_name`
            plus `last_name`, but kept as a separate field so the
            platform can render it consistently across receipts, intake
            forms and check-in screens.
          example: Jane Doe
    Discount:
      title: Discount
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the order discount
          type: string
          format: object-id
        amount_type:
          description: The type of the amount this discount describes.
          type: string
          enum:
            - monetary
            - percentage
        applicable_for:
          description: Where this discount type is able to be applied.
          type: string
          example: app_and_booking_engine
          enum:
            - app_and_booking_engine
            - app_only
          nullable: true
        applied_at:
          description: The date and time that the discount was applied.
          type: string
          format: date-time
        applied_by:
          description: |
            Information about the user who applied the discount.
            This will be null if the discount was applied by the customer.
          type: object
          nullable: true
          $ref: '#/components/schemas/UserSummary'
        calculated_amount:
          description: The total calculated amount of this discount.
          type: integer
          example: 150
        coupon:
          description: The summary of the coupon used to add this discount, if applicable.
          $ref: '#/components/schemas/BasketCouponSummary'
          nullable: true
        coupon_code_id:
          description: The ID of the coupon code used to add this discount, if applicable.
          type: string
          format: object-id
          nullable: true
        currency:
          $ref: '#/components/schemas/properties_currency'
        discount_amount:
          description: |
            The value of the discount to be applied when a discount type is used.
            This can be used as a monetary or percentage value for an in-app discount type and is set to percentage for a promo code.
          type: integer
          example: 15
        discount_type_code:
          description: The code for the discount type.
          type: string
          example: SUMMER23
        reason_code:
          description: A code to describe the reason for the discount.
          type: string
          example: general
        site_id:
          description: The ID of the site the discount is associated with.
          type: string
          format: uuid
      required:
        - id
        - amount_type
        - applicable_for
        - applied_at
        - applied_by
        - calculated_amount
        - coupon
        - coupon_code_id
        - currency
        - discount_amount
        - discount_type_code
        - reason_code
        - site_id
    ItemConfiguration:
      description: Type-specific properties to configure an order item.
      type: object
      additionalProperties: true
    OptionBudget:
      title: OrderPackageItemOptionBudget
      type: object
      additionalProperties: false
      properties:
        budget:
          description: The amount of the budget, in the smallest denomination.
          type: string
          nullable: true
        choice_id:
          description: The ID of the choice this option budget belongs to.
          type: string
        remaining:
          description: The amount of the budget remaining to be spent, in the smallest denomination.
          type: string
          nullable: true
        spent:
          description: The amount spent towards the budget, in the smallest denomination.
          type: string
          nullable: true
      required:
        - budget
        - choice_id
        - remaining
        - spent
    OfferingSummary:
      title: OfferingSummary
      description: Summary details of an offering.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the offering.
          type: string
          format: mongo-id
        name:
          description: The name of the offering.
          type: string
          example: 30 Minute Massage
        type:
          $ref: '#/components/schemas/OfferingType'
        product_code:
          type: string
          nullable: true
      required:
        - id
        - name
        - product_code
        - type
    PurchaseItemStatus:
      type: string
      enum:
        - cancelled
        - confirmed
        - pending_confirmation
        - reserved
        - waitlisted
    createdAt:
      description: When then resource was created.
      type: string
      format: date-time
      example: '2025-02-04T12:00:00+01:00'
    updatedAt:
      description: When then resource was last updated.
      type: string
      format: date-time
      example: '2025-02-04T12:00:00+01:00'
    AreaBookingSummary:
      title: AreaBookingSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        area_ids:
          type: array
          items:
            type: string
            format: object-id
        areas:
          type: array
          items:
            $ref: '#/components/schemas/BookableAreaSummary'
        duration:
          type: integer
        end_time:
          type: string
          format: date-time
        offering:
          $ref: '#/components/schemas/OfferingSummary'
        start_time:
          type: string
          format: date-time
        status:
          $ref: '#/components/schemas/PurchaseItemStatus'
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - area_ids
        - areas
        - duration
        - end_time
        - offering
        - start_time
        - status
        - created_at
        - updated_at
    EquipmentSummary:
      title: EquipmentSummary
      description: Summary details of a piece of equipment.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the equipment.
          type: string
          format: mongo-id
        name:
          description: The name of the equipment.
          type: string
          example: Hot Rocks
      required:
        - id
        - name
    BookingSummaryBookingSummary:
      title: BookingSummaryBookingSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        duration:
          type: integer
        end_time:
          type: string
          format: date-time
        equipment:
          type: array
          items:
            $ref: '#/components/schemas/EquipmentSummary'
        equipment_ids:
          type: array
          items:
            type: string
            format: object-id
        offering:
          $ref: '#/components/schemas/OfferingSummary'
        practitioners:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerSummary'
        practitioner_ids:
          type: array
          items:
            type: string
            format: object-id
        practitioner_was_requested:
          type: boolean
        room:
          $ref: '#/components/schemas/RoomSummary'
        room_id:
          type: string
          format: object-id
        room_was_requested:
          type: boolean
        session_id:
          type: string
          format: object-id
        start_time:
          type: string
          format: date-time
        status:
          $ref: '#/components/schemas/PurchaseItemStatus'
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - duration
        - end_time
        - equipment
        - equipment_ids
        - offering
        - practitioners
        - practitioner_ids
        - room
        - room_id
        - start_time
        - status
        - created_at
        - updated_at
    TableReservationSummary:
      title: TableReservationSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        duration:
          type: integer
        end_time:
          type: string
          format: date-time
        offering:
          $ref: '#/components/schemas/OfferingSummary'
        start_time:
          type: string
          format: date-time
        status:
          $ref: '#/components/schemas/PurchaseItemStatus'
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - duration
        - end_time
        - offering
        - start_time
        - status
        - created_at
        - updated_at
    BookingSummary:
      title: OrderBookingSummary
      oneOf:
        - $ref: '#/components/schemas/AreaBookingSummary'
        - $ref: '#/components/schemas/BookingSummaryBookingSummary'
        - $ref: '#/components/schemas/TableReservationSummary'
    Status:
      type: string
      enum:
        - cancelled
        - in_progress
        - new
        - no_show
        - settled
        - submitted
      example: submitted
    OrderItemPackageItem:
      title: OrderItemPackageItem
      description: A nested basket item that is part of a package.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the package item.
          type: string
          format: mongo-id
        booking_summary:
          $ref: '#/components/schemas/BookingSummary'
        choice_id:
          description: The ID of the package choice this item relates to.
          type: string
          format: mongo-id
        duration:
          description: The duration of the item in minutes.
          type: integer
          nullable: true
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        item_configuration:
          $ref: '#/components/schemas/ItemConfiguration'
        offering_id:
          description: The ID of the offering.
          type: string
          format: mongo-id
        offering_name:
          description: The name of the offering.
          type: string
          example: 60 minute massage
        offering_type:
          description: The offering type of this package item.
          type: string
          example: appointment
        option_id:
          description: The ID of the choice option that this item relates to.
          type: string
          format: mongo-id
        price_change:
          description: The amount by which this option changes the overall package price.
          type: integer
          example: 1500
        reserved_until:
          type: string
          format: date-time
        shared_basket_item_id:
          type: string
          format: object-id
        status:
          $ref: '#/components/schemas/Status'
        time:
          description: The start time of the item.
          type: string
          format: date-time
          nullable: true
      required:
        - id
        - choice_id
        - duration
        - item_configuration
        - offering_id
        - offering_name
        - offering_type
        - option_id
        - price_change
        - reserved_until
        - time
    PurchasableDetailsVoucher:
      title: BasketPurchasableDetailsVoucher
      type: object
      additionalProperties: false
      properties:
        delivery_date:
          type: string
          format: date-time
    Item:
      title: BasketItem
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        currency:
          $ref: '#/components/schemas/properties_currency'
        date:
          type: string
          format: date
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        duration:
          type: integer
        guest:
          deprecated: true
          $ref: '#/components/schemas/Guest'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        image:
          $ref: '#/components/schemas/Media'
        item_configuration:
          $ref: '#/components/schemas/ItemConfiguration'
        net_total:
          type: integer
        offering_categories:
          type: array
          items:
            title: BasketOfferingCategory
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
              name:
                type: string
            required:
              - id
              - name
        offering_id:
          type: string
          format: object-id
        offering_name:
          type: string
        offering_type:
          $ref: '#/components/schemas/OfferingType'
        option_budgets:
          type: array
          items:
            $ref: '#/components/schemas/OptionBudget'
        package_items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItemPackageItem'
        price:
          type: integer
          nullable: true
        purchasable_details:
          oneOf:
            - $ref: '#/components/schemas/PurchasableDetailsVoucher'
            - title: BasketPurchasableDetailsMembership
              type: object
              additionalProperties: false
              properties:
                membership_rate_id:
                  type: string
                  format: object-id
                membership_type_id:
                  type: string
                  format: object-id
                membership_type_name:
                  type: string
                purchasable_id:
                  type: string
                  format: object-id
                  nullable: true
                rate:
                  title: BasketPurchasableDetailsMembershipRate
                  type: object
                  additionalProperties: false
                  properties:
                    billing_frequency:
                      type: string
                    currency:
                      $ref: '#/components/schemas/properties_currency'
                    default_duration:
                      type: integer
                    amount:
                      type: string
                  required:
                    - billing_frequency
                    - currency
                    - default_duration
                    - amount
                joining_fee:
                  title: BasketPurchasableDetailsMembershipJoiningFee
                  type: object
                  additionalProperties: false
                  properties:
                    amount:
                      type: integer
                    currency:
                      $ref: '#/components/schemas/properties_currency'
                  required:
                    - amount
                    - currency
        quantity:
          type: integer
        reserved_until:
          type: string
          format: date-time
          nullable: true
        tax_amount:
          type: integer
        tax_percent:
          type: integer
        time:
          type: string
          format: date-time
        total_cost:
          type: integer
          nullable: true
        validity:
          title: BasketItemValidity
          type: object
          additionalProperties: false
          properties:
            errors:
              type: array
              items:
                title: BasketItemValidityError
                type: object
                additionalProperties: false
                properties:
                  message:
                    type: string
            valid:
              type: boolean
          required:
            - errors
            - valid
        will_be_waitlisted:
          type: boolean
      required:
        - id
        - currency
        - date
        - discounts
        - duration
        - guests
        - net_total
        - offering_categories
        - offering_id
        - offering_name
        - offering_type
        - package_items
        - price
        - quantity
        - reserved_until
        - tax_amount
        - tax_percent
        - time
        - total_cost
    Chargeback:
      title: Chargeback
      description: An instance of a chargeback that was created for a payment.
      type: object
      additionalProperties: false
      required:
        - id
        - amount
        - currency
        - payment_id
        - processor_data
        - reason
        - status
        - created_at
      properties:
        id:
          type: string
          format: object-id
        amount:
          type: string
        currency:
          $ref: '#/components/schemas/properties_currency'
        payment_id:
          description: The ID of the payment that was charged back.
          type: string
          format: object-id
        processor_data:
          type: object
          additionalProperties: true
        reason:
          description: The reason for the chargeback.
          type: string
        status:
          type: string
          enum:
            - confirmed
            - pending
            - processed
            - reversed
        created_at:
          $ref: '#/components/schemas/createdAt'
    PaymentItemRevenue:
      title: PaymentItemRevenue
      description: A portion of a payment allocated to a specific order item and revenue centre, recording how much of the payment covers that revenue line.
      type: object
      additionalProperties: false
      properties:
        basket_item_id:
          description: The ID of the order item that this allocation covers.
          type: string
          format: object-id
        revenue_centre:
          description: The revenue centre of the order item's revenue line that this allocation covers.
          type: string
          example: spa
        gross_amount:
          description: The gross amount of the payment allocated to this revenue line, in the lowest denomination.
          type: integer
          example: 1500
        net_amount:
          description: The net amount of the payment allocated to this revenue line, in the lowest denomination.
          type: integer
          example: 1250
        refunded_amount:
          description: The amount of this allocation that has been refunded, in the lowest denomination.
          type: integer
          example: 0
        currency:
          description: The currency code for the allocated amounts.
          $ref: '#/components/schemas/properties_currency'
      required:
        - basket_item_id
        - revenue_centre
        - gross_amount
        - net_amount
        - refunded_amount
        - currency
    Refund:
      title: Refund
      description: An instance of a refund.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the refund.
          type: string
          format: object-id
        payment_id:
          description: The ID of the payment that was refunded.
          type: string
          format: object-id
        amount:
          description: The amount of the refund.
          type: integer
          format: integer
        currency:
          $ref: '#/components/schemas/properties_currency'
        notes:
          description: Notes that were added against the refund.
          type: string
          nullable: true
        status:
          description: The current status of the refund.
          type: string
          enum:
            - pending
            - complete
            - failed
        processor_data:
          description: A dictionary of processor-specific data.
          type: object
          additionalProperties: true
        created_at:
          description: The date and time that the refund was created.
          type: string
          format: date-time
      required:
        - id
        - payment_id
        - amount
        - currency
        - status
        - created_at
        - processor_data
    Payment:
      title: Payment
      type: object
      description: An instance of a payment against an order.
      additionalProperties: false
      properties:
        id:
          description: The ID of the item to be added.
          type: string
          format: object-id
        amount:
          description: The amount of the payment, in the lowest denomination
          type: integer
          example: 10000
        capture_method:
          description: At what point the payment amount will be captured
          type: string
          nullable: true
          example: automatic
        chargebacks:
          type: array
          items:
            $ref: '#/components/schemas/Chargeback'
        currency:
          description: The currency code for the amount
          $ref: '#/components/schemas/properties_currency'
        details_source:
          description: How the payment method will be provided
          type: string
          nullable: true
          example: pay_by_link
        failure_reason:
          description: If present, provides a human-readable explanation for the failure.
          type: string
          nullable: true
          example: Suspected fraud
        item_revenues:
          description: How the payment amount is allocated across the order's items and revenue centres. Null for payments taken before item revenue allocation was enabled — such payments cannot support item-level operations like partial charge to room.
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/PaymentItemRevenue'
        order_ref:
          type: string
          nullable: true
        paid_at:
          description: The time and date that the payment was paid.
          type: string
          format: date-time
          nullable: true
          example: '2020-02-24T12:00:00+01:00'
        payable_id:
          type: string
          format: object-id
        payable_type:
          type: string
        processor:
          description: The payment processor to be used for the payment
          type: string
          example: stripe
        processor_data:
          description: A dictionary of processor-specific data
          type: object
          additionalProperties: true
        processor_id:
          type: string
          format: object-id
        processor_type:
          type: string
          nullable: true
        refundable_amount:
          description: The amount of the payment that may be refunded.
          type: number
          example: 3500
        refunds:
          type: array
          items:
            $ref: '#/components/schemas/Refund'
        status:
          description: The current status of the payment
          type: string
          enum:
            - cancelled
            - expired
            - failed
            - paid
            - payment_method_charged
            - payment_method_stored
            - pending
            - ready_for_capture
            - requires_action
        created_at:
          description: The time and date that the payment was created.
          $ref: '#/components/schemas/createdAt'
      required:
        - id
        - amount
        - capture_method
        - currency
        - details_source
        - item_revenues
        - paid_at
        - payable_id
        - payable_type
        - processor
        - processor_id
        - processor_data
        - processor_type
        - refundable_amount
        - refunds
        - status
        - created_at
    VoucherSummary:
      type: object
      title: VoucherSummary
      additionalProperties: false
      properties:
        id:
          description: The ID of the voucher.
          type: string
          format: uuid
        amount_type:
          description: The amount type of the voucher.
          type: string
          example: discount_to_zero
        calculated_amount:
          description: The calculated amount of the voucher.
          type: integer
          example: 1000
        code:
          description: The code of the voucher.
          type: string
          example: ABCDEFGHIJ123
        coupon_code_id:
          description: The ID of the coupon that created the voucher, if applicable.
          type: string
          format: object-id
        description:
          description: The description of the voucher.
          type: string
          nullable: true
          example: A 30 minute treatment of your choice.
        is_redeemed:
          description: Whether the voucher has been redeemed.
          type: boolean
        name:
          description: The name of the voucher.
          type: string
          example: 30 min treatment
        voucher_type_id:
          description: The ID of the voucher type.
          type: string
          format: object-id
      required:
        - id
        - name
        - amount_type
        - code
        - description
        - name
        - voucher_type_id
    Basket:
      title: Basket
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        applied_promo_code:
          $ref: '#/components/schemas/AppliedPromoCode'
        applied_promo_code_discount_total:
          type: integer
        applied_promo_code_id:
          type: string
          nullable: true
        coupon_codes:
          type: array
          items:
            $ref: '#/components/schemas/BasketCouponSummary'
        currency:
          $ref: '#/components/schemas/properties_currency'
        customer_id:
          type: string
          format: uuid
        discount_total:
          type: integer
        email:
          type: string
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        first_name:
          type: string
        is_promo_code_discount_applied:
          type: boolean
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
        items_reserved_until:
          type: string
          format: date-time
          nullable: true
        last_name:
          type: string
        net_total:
          type: integer
        order_ref:
          type: string
          nullable: true
        organisation_id:
          type: string
          format: uuid
        outstanding_payment_amount:
          type: integer
        payments:
          type: array
          items:
            $ref: '#/components/schemas/Payment'
        phone:
          type: string
        promo_code_applied_at:
          type: string
          format: date-time
        promo_code_applied_by:
          $ref: '#/components/schemas/UserSummary'
        site_id:
          type: string
          format: uuid
        special_requests:
          type: string
          nullable: true
        status:
          description: The status of the `Basket`.
          $ref: '#/components/schemas/Status'
        submit_auth_amount:
          type: integer
          nullable: true
        submit_errors:
          type: array
          items:
            title: BasketSubmitError
            type: object
            additionalProperties: false
            properties:
              error:
                type: string
              message:
                type: string
              time:
                type: integer
            required:
              - error
              - message
              - time
        submit_payment_amount:
          type: integer
          nullable: true
        submitted_at:
          type: string
          format: date-time
          nullable: true
        total_cost:
          type: integer
        total_paid_or_authed:
          type: integer
        total_tax:
          type: integer
        totals:
          title: BasketTotals
          type: object
          additionalProperties: false
          properties:
            applied_vouchers:
              type: integer
            auth_required:
              type: integer
            discounts:
              type: integer
            gross_total:
              type: integer
            net_total:
              type: integer
            payment_required:
              type: integer
            tax:
              type: integer
          required:
            - applied_vouchers
            - auth_required
            - discounts
            - gross_total
            - net_total
            - payment_required
            - tax
        voucher_codes:
          type: array
          items:
            $ref: '#/components/schemas/VoucherSummary'
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - applied_promo_code_discount_total
        - applied_promo_code_id
        - coupon_codes
        - currency
        - customer_id
        - email
        - discount_total
        - first_name
        - guests
        - is_promo_code_discount_applied
        - items
        - items_reserved_until
        - last_name
        - net_total
        - order_ref
        - organisation_id
        - outstanding_payment_amount
        - payments
        - phone
        - site_id
        - special_requests
        - status
        - submit_auth_amount
        - submit_payment_amount
        - submitted_at
        - total_cost
        - total_paid_or_authed
        - total_tax
        - totals
        - voucher_codes
        - created_at
        - updated_at
    Category:
      title: ShopOfferingCategory
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        name:
          type: string
      required:
        - id
        - name
    Appointment:
      title: ShopOfferingAppointment
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        currency:
          $ref: '#/components/schemas/properties_currency'
        description:
          type: string
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        duration:
          type: integer
          nullable: true
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        has_availability:
          type: boolean
        image:
          $ref: '#/components/schemas/Media'
        max_guests:
          type: integer
        min_guests:
          type: integer
        name:
          type: string
        price_from:
          type: integer
          nullable: true
        price_to:
          type: integer
          nullable: true
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this offering, in the smallest currency
            unit (e.g. pence). `null` if a standard price hasn't been
            configured — this is distinct from a price of zero.
        type:
          type: string
          enum:
            - appointment
      required:
        - id
        - currency
        - description
        - discounts
        - duration
        - external_id
        - has_availability
        - max_guests
        - min_guests
        - name
        - price_from
        - price_to
        - standard_price
        - type
    AreaBooking:
      title: ShopOfferingAreaBooking
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        currency:
          $ref: '#/components/schemas/properties_currency'
        description:
          type: string
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        durations:
          type: array
          items:
            type: integer
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        has_availability:
          type: boolean
        image:
          $ref: '#/components/schemas/Media'
        max_duration:
          type: integer
          nullable: true
        min_duration:
          type: integer
          nullable: true
        name:
          type: string
        price_from:
          type: integer
          nullable: true
        price_to:
          type: integer
          nullable: true
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this offering, in the smallest currency
            unit (e.g. pence). `null` if a standard price hasn't been
            configured — this is distinct from a price of zero.
        type:
          type: string
          enum:
            - area_booking
      required:
        - id
        - currency
        - description
        - discounts
        - durations
        - external_id
        - has_availability
        - max_duration
        - min_duration
        - name
        - price_from
        - price_to
        - standard_price
        - type
    PackageShopOffering:
      title: PackageShopOffering
      type: object
      additionalProperties: false
      required:
        - id
        - currency
        - description
        - external_id
        - name
      properties:
        id:
          type: string
          description: The ID of the offering
          example: 5e932c0901d210625e3a8766
        categories:
          type: array
          items:
            title: PackageShopOfferingCategory
            type: object
            additionalProperties: false
            required:
              - id
              - name
            properties:
              id:
                type: string
                description: The ID of the category
                example: 5e932c0901d210625e3a8766
              name:
                type: string
                description: The name of the category
                example: Massage
        currency:
          type: string
          description: The currency code for the price
          example: gbp
        description:
          type: string
          description: The name of the offering
          example: Choose from classic, deep tissue and Swedish massage
        discounted_price_from:
          type: integer
          description: If set, a discounted 'price from' that applies to the current customer
          example: 4500
        duration:
          type: integer
          description: The duration of the offering in minutes
          example: 30
        durations:
          type: array
          items:
            type: integer
            description: Present if the `type` is area_booking. Contains an array of durations, in minutes, valid for this offering.
            example: 30
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        has_availability:
          type: boolean
          description: Whether there is availability for the offering on the requested date.
          example: true
        image:
          description: A url to an image for the offering
          $ref: '#/components/schemas/Media'
        max_guests:
          type: integer
          description: The maximum guests this offering is for
          example: 2
        min_guests:
          type: integer
          description: The minimum guests this offering is for
          example: 2
        name:
          type: string
          description: The name of the offering
          example: 60 minute massage
        next_available_date:
          type: string
          format: date
          description: The next available date if there is no availability on the given date
        price_from:
          type: integer
          description: The minimum price of the offering on the given date
          example: 5000
        price_to:
          type: integer
          description: The maximum price of the offering on the given date
          example: 6500
        type:
          type: string
          description: Identifies the type of this model
          example: appointment
    PackageItemChoiceOption:
      title: PackageItemChoiceOption
      type: object
      additionalProperties: false
      required:
        - id
        - item_type
        - offering
        - price_change
      properties:
        id:
          type: string
          description: |
            Identifier of the offering this option points at — an
            `AppointmentType`, `SessionType` or retail `Product`,
            depending on `item_type`. The guest sees the offering's name
            and image when picking this option in the storefront.
          example: 5dcb47800000000000000026
        item_type:
          type: string
          description: The type of item this option represents.
          example: appointment
        offering:
          $ref: '#/components/schemas/PackageShopOffering'
          readOnly: true
          nullable: true
        price_change:
          type: integer
          nullable: true
          description: A currency amount that this option would increase the package price by.
          example: 2000
    PackageChoiceStartTimeRule:
      title: PackageChoiceStartTimeRule
      type: object
      additionalProperties: false
      required:
        - absolute_time_from
        - absolute_time_to
        - relative_mins_from
        - relative_mins_to
        - relative_to
        - type
      properties:
        absolute_time_from:
          type: string
          description: The earliest allowed start time.
          example: '12:00'
          nullable: true
        absolute_time_to:
          type: string
          description: The latest allowed start time.
          example: '12:30'
          nullable: true
        relative_mins_from:
          type: integer
          description: The minimum number of minutes from the relative base point that should be allowed.
          example: 0
          nullable: true
        relative_mins_to:
          type: integer
          description: The maximum number of minutes from the relative base point that should be allowed.
          example: 30
          nullable: true
        relative_to:
          type: string
          description: The base time that a relative start time should be calculated from.
          enum:
            - first_item_start
          nullable: true
        type:
          type: string
          description: The type of the rule.
          enum:
            - relative
            - absolute
    PackageItemChoice:
      title: PackageItemChoice
      type: object
      additionalProperties: false
      required:
        - id
        - allocation
        - allow_overlaps
        - auto_select_timeslot
        - choice_configuration
        - description
        - hide_times
        - name
        - max_options
        - min_options
        - offering_type
        - option_budget
        - optional
        - options
        - start_time_rules
        - visible
      properties:
        id:
          type: string
          description: The ID of this choice.
          example: 5dcb47800000000000000025
        allocation:
          title: PackageItemChoiceAllocation
          type: object
          additionalProperties: false
          required:
            - amount
            - revenue_centre
          properties:
            amount:
              type: integer
            revenue_centre:
              type: string
        allow_overlaps:
          type: boolean
          description: Allow this choice to overlap with other items when `prevent_choice_overlaps` is enabled on the package.
          example: true
        auto_select_timeslot:
          type: boolean
          description: Whether a timeslot should be automatically selected for this choice
          example: true
        choice_configuration:
          type: object
          description: Any additional configuration for this choice.
          additionalProperties: true
        description:
          type: string
          description: A description of this choice.
          example: Choose your type of massage.
        hide_times:
          type: boolean
          description: Whether to hide times for this choice from customers
          example: true
        name:
          type: string
          description: A name for this choice.
          example: Massage
        max_options:
          type: integer
          nullable: true
          description: The maximum number of options that may be chosen.
          example: 2
        min_options:
          type: integer
          nullable: true
          description: The minimum number of options that must be chosen.
          example: 1
        offering_type:
          type: string
          description: The type of offerings included in this choice.
          enum:
            - appointment
            - product
            - session
        option_budget:
          type: integer
          description: |
            The budget that this package allows for options in this choice.
            Each option will use its standalone price, and the overall package
            price will be increased if the total exceeds the budget.
          example: 2000
        optional:
          type: boolean
          description: Whether this item choice should be optional.
          example: true
        options:
          type: array
          description: An array of options to make up this choice.
          items:
            $ref: '#/components/schemas/PackageItemChoiceOption'
        start_time_rules:
          type: array
          description: An array of rules determining the start times that should be allowed for this choice.
          items:
            $ref: '#/components/schemas/PackageChoiceStartTimeRule'
        visible:
          type: boolean
          description: Whether this item choice should be visible to the customer.
          example: true
    Package:
      title: ShopOfferingPackage
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        currency:
          $ref: '#/components/schemas/properties_currency'
        description:
          type: string
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        has_availability:
          type: boolean
        image:
          $ref: '#/components/schemas/Media'
        item_choices:
          type: array
          items:
            $ref: '#/components/schemas/PackageItemChoice'
        max_guests:
          type: integer
        min_guests:
          type: integer
        name:
          type: string
        price_from:
          type: integer
          nullable: true
        price_to:
          type: integer
          nullable: true
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this offering, in the smallest currency
            unit (e.g. pence). `null` if a standard price hasn't been
            configured — this is distinct from a price of zero.
        type:
          type: string
          enum:
            - package
      required:
        - id
        - categories
        - currency
        - description
        - external_id
        - has_availability
        - item_choices
        - max_guests
        - min_guests
        - name
        - price_from
        - price_to
        - standard_price
        - type
    Product:
      title: ShopOfferingProduct
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        currency:
          $ref: '#/components/schemas/properties_currency'
        description:
          type: string
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        has_inventory:
          type: boolean
        image:
          $ref: '#/components/schemas/Media'
        name:
          type: string
        price:
          type: integer
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this offering, in the smallest currency
            unit (e.g. pence). `null` if a standard price hasn't been
            configured — this is distinct from a price of zero.
        type:
          type: string
          enum:
            - product
      required:
        - id
        - currency
        - description
        - external_id
        - has_inventory
        - name
        - price
        - standard_price
        - type
    Session:
      title: ShopOfferingSession
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        currency:
          $ref: '#/components/schemas/properties_currency'
        description:
          type: string
        duration:
          type: integer
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        has_availability:
          type: boolean
        image:
          $ref: '#/components/schemas/Media'
        name:
          type: string
        next_available_date:
          type: string
          format: date
          nullable: true
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        price_from:
          type: integer
          nullable: true
        price_to:
          type: integer
          nullable: true
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this offering, in the smallest currency
            unit (e.g. pence). `null` if a standard price hasn't been
            configured — this is distinct from a price of zero.
        type:
          type: string
          enum:
            - session
      required:
        - id
        - categories
        - currency
        - description
        - duration
        - external_id
        - name
        - price_from
        - price_to
        - standard_price
        - type
    TerminalRequest:
      title: TerminalRequest
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the request.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the request is associated with.
        terminal_id:
          type: string
          description: The serial number of the terminal associated with the request.
        service_id:
          type: string
          description: The ID of the service the request is associated with.
        status:
          type: string
          enum:
            - pending
            - succeeded
            - failed
          description: The status of the request.
        amount:
          type: integer
          description: The amount being sent to the terminal in the request.
          nullable: true
        succeeded_at:
          type: string
          format: date-time
          description: The date and time the request was successfully completed.
          nullable: true
        failed_at:
          type: string
          format: date-time
          description: The date and time the request failed.
          nullable: true
        processor_data:
          type: object
          additionalProperties: true
          description: |
            An object of key-value pairs containing the response from the terminal operation.
      required:
        - id
        - site_id
        - terminal_id
        - service_id
        - status
        - amount
        - succeeded_at
        - failed_at
        - processor_data
    CardTokenisationRequest:
      title: CardTokenisationRequest
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the tokenisation request.
        status:
          type: string
          enum:
            - pending
            - paid
            - failed
            - cancelled
          description: The status of the tokenisation request.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the tokenisation request is associated with.
        terminal_id:
          type: string
          description: The serial number of the terminal associated with the tokenisation request.
        service_id:
          type: string
          description: The ID of the service the tokenisation request is associated with.
        processor_data:
          type: object
          title: TokenisationRequestProcessorData
          additionalProperties: true
          description: |
            An object of key-value pairs containing the response from the terminal for the tokenisation request.
      required:
        - id
        - status
        - site_id
        - terminal_id
        - service_id
        - processor_data
    schemas_Appointment:
      title: Appointment
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the appointment.
          type: string
          format: object-id
        appointment_type_id:
          description: The ID of the appointment type.
          type: string
          format: object-id
        appointment_type_name:
          description: The name of the appointment type.
          type: string
          example: 60 minute massage
        currency:
          $ref: '#/components/schemas/properties_currency'
        customer_id:
          description: The ID of the customer this appointment is for.
          type: string
          format: object-id
        duration:
          description: The duration of the appointment in minutes.
          type: integer
          example: 60
        email:
          description: The email address of the customer.
          type: string
          example: janedoe@example.com
        end_buffer:
          description: The number of minutes blocked out at the end of the appointment for cleaning or changeover.
          type: integer
          example: 15
        end_time:
          description: The end time this appointment is for.
          type: string
          format: date-time
          example: '2019-01-15T13:00:00+01:00'
        first_name:
          description: The first name of the customer.
          type: string
          example: Jane
        full_name:
          description: The full name of the customer.
          type: string
          example: Jane Doe
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        has_notes:
          description: Whether the appointment belongs to an order that has notes.
          type: boolean
          example: true
        has_outstanding_balance:
          description: Whether the appointment belongs to an order that has an outstanding balance.
          type: boolean
          example: true
        has_special_requests:
          description: Whether the appointment belongs to an order that has special requests.
          type: boolean
          example: true
        is_group_booking:
          description: Whether the appointment belongs to an order that has multiple guests.
          type: boolean
          example: true
        is_hotel_room_booking:
          description: Whether the appointment belongs to an order that is associated with a hotel room.
          type: boolean
          example: true
        is_locked:
          description: Whether the appointment is locked and should not be moved.
          type: boolean
          example: true
        is_part_of_package:
          description: Whether the appointment was sold as part of a package
          type: boolean
          example: true
        last_name:
          description: The last name of the customer.
          type: string
          example: Doe
        net_total:
          description: The net total of the appointment.
          type: integer
          example: 4950
        order_id:
          description: The ID of the order associated with this appointment.
          type: string
          format: object-id
        order_is_locked:
          description: Whether the order is locked
          type: boolean
          example: false
        order_item_id:
          description: The ID of the order item associated with this appointment.
          type: string
          format: object-id
        order_labels:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Label'
        order_locked_at:
          description: The date the order was locked at
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
        order_ref:
          description: The order reference associated with this appointment.
          type: string
          example: TRY00
        organisation_id:
          description: The ID of the organisation the appointment belongs to.
          type: string
          format: uuid
        package_product_code:
          description: The product code for the package.
          type: string
          example: MAS123
        phone:
          description: The customer's phone number.
          type: string
          example: '+447727123456'
        practitioner_ids:
          description: The IDs of the practitioners this appointment assigned to.
          type: array
          items:
            type: string
            format: object-id
        practitioners:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerSummary'
        product_code:
          description: A custom product code for the product.
          type: string
          nullable: true
          example: MAS123
        room:
          $ref: '#/components/schemas/RoomSummary'
        room_id:
          description: The ID of the room this appointment assigned to.
          type: string
          format: object-id
        site_id:
          description: The ID of the site the appointment belongs to.
          type: string
          format: uuid
        stage:
          description: The current stage of the order the appointment belongs to.
          type: string
          enum:
            - arrived
            - checked_out
            - in_treatment
            - not_arrived
        start_time:
          description: The start time this appointment is for.
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
        status:
          description: The status of the appointment.
          type: string
          enum:
            - confirmed
            - in_progress
            - new
        submitted_at:
          description: The date and time the appointment was submitted.
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
        total_cost:
          description: The total cost of the appointment.
          type: integer
          example: 5000
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - appointment_type_id
        - appointment_type_name
        - customer_id
        - duration
        - email
        - end_buffer
        - end_time
        - first_name
        - guests
        - has_notes
        - has_outstanding_balance
        - has_special_requests
        - is_group_booking
        - is_part_of_package
        - last_name
        - net_total
        - order_id
        - order_is_locked
        - order_item_id
        - order_labels
        - order_ref
        - organisation_id
        - phone
        - practitioner_ids
        - practitioners
        - product_code
        - room
        - room_id
        - site_id
        - stage
        - start_time
        - status
        - submitted_at
        - total_cost
        - created_at
        - updated_at
    Totals:
      title: ListAppointmentsTotals
      type: object
      additionalProperties: false
      properties:
        net_total:
          type: integer
        total_items:
          type: integer
      required:
        - net_total
        - total_items
    UpdateAppointment:
      title: UpdateAppointment
      description: |
        Body for `updateAppointment`. Every field is optional; pass only
        the fields you want to change. Time-based fields are validated
        against the same availability rules as the booking flow.
      type: object
      additionalProperties: false
      properties:
        practitioner_ids:
          description: |
            Replace the set of practitioners assigned to this appointment.
            Pass an empty array to clear all assignments. Each ID must
            belong to a practitioner who can perform this
            `AppointmentType` at this site.
          type: array
          nullable: true
          items:
            type: string
            format: object-id
          example:
            - 5e932c0901d210625e3a8766
        room_id:
          description: |
            Replace the room assigned to this appointment. The room must
            be one of the rooms permitted by the `AppointmentType` and
            available for the appointment's time slot.
          type: string
          format: object-id
          nullable: true
          example: 5e932c0901d210625e3a8767
        start_time:
          description: |
            Reschedule the appointment to start at this date and time. The
            end time is recalculated from the appointment's `duration` and
            `end_buffer`. Must be an RFC 3339 timestamp with offset.
          type: string
          format: date-time
          example: '2026-06-01T10:00:00+01:00'
        time:
          description: |
            **Deprecated**. Legacy alias for `start_time`. Will be removed
            once all calendar drag-and-drop clients have migrated.
          type: string
          format: date-time
          deprecated: true
          example: '2026-06-01T10:00:00+01:00'
        move:
          title: UpdateAppointmentMove
          description: |
            Convenience block for calendar drag-and-drop. Specifies which
            practitioner or room is being swapped without restating the
            whole list. When `resource_type` is `practitioner`,
            `practitioner_ids` is updated automatically; when `room`, the
            `room_id` is updated.
          type: object
          additionalProperties: false
          properties:
            from_id:
              description: ID of the resource being moved off the appointment.
              type: string
              nullable: true
              example: 5e932c0901d210625e3a8766
            to_id:
              description: ID of the resource being moved onto the appointment.
              type: string
              example: 5e932c0901d210625e3a8767
            resource_type:
              description: Which resource is being moved.
              type: string
              enum:
                - practitioner
                - room
          required:
            - to_id
            - resource_type
        stage:
          description: |
            Move the underlying order through its check-in flow. When
            `stage` is the only field provided the availability layer is
            skipped entirely. Pass `null` to clear the stage back to the
            default.
          type: string
          nullable: true
          enum:
            - arrived
            - in_treatment
            - checked_out
            - not_arrived
    schemas_AreaBooking:
      title: AreaBooking
      description: |
        A confirmed booking of one or more `BookableArea`s — for example a
        cabana, treatment pod, or pool deck — against a customer order.
        An `AreaBooking` is created by the basket pipeline when an
        `AreaBookingType` is added to a basket, and remains the source of
        truth for the reservation throughout its life-cycle.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the area booking.
          type: string
          format: object-id
        area_booking_type_id:
          description: The ID of the `AreaBookingType` this booking is for.
          type: string
          format: object-id
        area_booking_type_name:
          description: |
            The name of the `AreaBookingType` at the time the booking was
            made. This is captured at booking time so the value remains
            stable even if the parent type is later renamed.
          type: string
          example: Pool Cabana
        order_id:
          description: The ID of the order this area booking belongs to.
          type: string
          format: object-id
        order_ref:
          description: The human-readable reference of the parent order.
          type: string
          example: TRY00
        order_item_id:
          description: The ID of the `OrderItem` this area booking represents.
          type: string
          format: object-id
        order_labels:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Label'
        order_is_locked:
          description: Whether the parent order has been locked from further changes.
          type: boolean
          example: false
        order_locked_at:
          description: The date and time the parent order was locked, if it has been.
          type: string
          format: date-time
          nullable: true
        status:
          description: The current status of the area booking.
          type: string
          enum:
            - confirmed
            - in_progress
            - new
        stage:
          description: The check-in stage of the parent order.
          type: string
          nullable: true
          enum:
            - arrived
            - in_treatment
            - checked_out
            - not_arrived
        customer_id:
          description: The ID of the customer the booking is for.
          type: string
          format: object-id
        email:
          description: The customer's email address.
          type: string
          example: janedoe@example.com
        phone:
          description: The customer's phone number.
          type: string
          example: '+447727123456'
        first_name:
          description: The customer's first name.
          type: string
          example: Jane
        last_name:
          description: The customer's last name.
          type: string
          example: Doe
        area_ids:
          description: The IDs of the `BookableArea`s assigned to this booking.
          type: array
          items:
            type: string
            format: object-id
        areas:
          description: Summary records for each assigned `BookableArea`.
          type: array
          items:
            $ref: '#/components/schemas/BookableAreaSummary'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        start_time:
          description: When the booking starts.
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
        end_time:
          description: When the booking ends.
          type: string
          format: date-time
          example: '2019-01-15T13:00:00+01:00'
        duration:
          description: The duration of the booking in minutes.
          type: integer
          example: 60
        end_buffer:
          description: Minutes blocked out after the booking for changeover or cleaning.
          type: integer
          example: 15
        is_group_booking:
          description: Whether the parent order has more than one guest.
          type: boolean
          example: false
        has_outstanding_balance:
          description: Whether the parent order still has unpaid balance.
          type: boolean
          example: false
        has_notes:
          description: Whether the parent order has any notes.
          type: boolean
          example: false
        has_special_requests:
          description: Whether the parent order has special requests recorded.
          type: boolean
          example: false
        product_code:
          description: A custom product code for the `AreaBookingType`.
          type: string
          example: SPA-CABANA
        is_part_of_package:
          description: Whether this booking was sold as part of a `Package`.
          type: boolean
          example: false
        package_product_code:
          description: The product code of the parent `Package`, if any.
          type: string
        organisation_id:
          description: The ID of the organisation the booking belongs to.
          type: string
          format: uuid
        site_id:
          description: The ID of the site the booking belongs to.
          type: string
          format: uuid
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - area_booking_type_id
        - area_booking_type_name
        - order_id
        - order_ref
        - order_item_id
        - order_labels
        - order_is_locked
        - status
        - customer_id
        - email
        - phone
        - first_name
        - last_name
        - area_ids
        - areas
        - guests
        - start_time
        - end_time
        - duration
        - end_buffer
        - is_group_booking
        - has_outstanding_balance
        - has_notes
        - has_special_requests
        - product_code
        - is_part_of_package
        - organisation_id
        - site_id
        - created_at
        - updated_at
    UpdateAreaBooking:
      title: UpdateAreaBooking
      description: |
        Body for `updateAreaBooking`. Every field is optional; pass only
        the fields you want to change. Time, duration, and area
        reassignments are revalidated against the same availability rules
        that the basket booking flow uses.
      type: object
      additionalProperties: false
      properties:
        area_ids:
          description: |
            Replace the set of `BookableArea`s assigned to this booking.
            Each area must permit the parent `AreaBookingType` and must be
            available for the booking's time slot.
          type: array
          nullable: true
          items:
            type: string
            format: object-id
          example:
            - 5e932c0901d210625e3a8766
        start_time:
          description: |
            Move the booking so it starts at this date and time. If
            `end_time` is not also supplied it will be recalculated from
            the existing duration. Must be an RFC 3339 timestamp with
            offset.
          type: string
          format: date-time
          example: '2026-06-01T10:00:00+01:00'
        end_time:
          description: |
            Move the booking so it ends at this date and time. Must be an
            RFC 3339 timestamp with offset and must be after `start_time`.
          type: string
          format: date-time
          example: '2026-06-01T12:00:00+01:00'
        time:
          description: |
            **Deprecated**. Legacy alias for `start_time`. Will be removed
            once all calendar drag-and-drop clients have migrated.
          type: string
          format: date-time
          deprecated: true
          example: '2026-06-01T10:00:00+01:00'
        duration:
          description: |
            Set the booking duration in minutes. Must be positive. When
            only `duration` is supplied the booking's `end_time` is
            recalculated from the current `start_time`.
          type: integer
          minimum: 1
          example: 60
        stage:
          description: |
            Move the parent order through its check-in flow. When `stage`
            is the only field provided the availability layer is skipped
            entirely. Pass `null` to clear the stage back to the default.
          type: string
          nullable: true
          enum:
            - arrived
            - in_treatment
            - checked_out
            - not_arrived
    VoucherCodeVoucherTypeRef:
      title: VoucherCodeVoucherTypeRef
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the `VoucherType` the voucher was issued against.
          type: string
          format: object-id
        name:
          description: The customer-facing name of the `VoucherType`.
          type: string
          example: Spa Day Gift Voucher
      required:
        - id
        - name
    VoucherCodeRecipient:
      title: VoucherCodeRecipient
      description: |
        Recipient details captured at purchase time for gift vouchers. All
        fields are nullable — for self-purchase or digital vouchers the
        block may be entirely empty.
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
          example: Jane Doe
        email:
          type: string
          nullable: true
          example: jane@example.com
        custom_message:
          description: A free-form message the purchaser left for the recipient.
          type: string
          nullable: true
        address_line1:
          type: string
          nullable: true
        address_line2:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        county:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        postcode:
          type: string
          nullable: true
      required:
        - name
        - email
        - custom_message
        - address_line1
        - address_line2
        - city
        - county
        - country
        - postcode
    VoucherDeliveryOption:
      type: object
      title: VoucherDeliveryOption
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier for the voucher delivery option
        name:
          type: string
          description: A name to identify this voucher delivery option
          example: First class mail
        description:
          type: string
          description: A description of this voucher delivery option
          nullable: true
        site_id:
          type: string
          format: uuid
          description: The site ID that this voucher delivery option belongs to
        archived:
          type: boolean
          description: When 'true', only archived voucher delivery options will be returned
          example: false
        price:
          type: number
          description: The price of the voucher delivery option as an integer of the smallest unit eg pence.
          example: 5000
        revenue_centre:
          type: string
          nullable: true
          description: Contains the revenue centre ID if this line is for revenue.
          example: spa
      required:
        - id
        - name
        - description
        - site_id
        - price
        - archived
        - revenue_centre
    VoucherCodeDelivery:
      title: VoucherCodeDelivery
      description: |
        How and when the voucher should be delivered to the recipient.
      type: object
      additionalProperties: false
      properties:
        method:
          description: |
            The delivery channel — typically `email`, `post`, or the
            special value `print_at_home` for self-service downloads.
          type: string
          nullable: true
          example: post
        option:
          $ref: '#/components/schemas/VoucherDeliveryOption'
        date:
          description: The date the voucher should be delivered on.
          type: string
          format: date-time
          nullable: true
      required:
        - method
        - date
    VoucherCodeOrderRef:
      title: VoucherCodeOrderRef
      description: The order the voucher was purchased on.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the parent order.
          type: string
          format: object-id
          nullable: true
        customer_id:
          description: The ID of the purchasing customer.
          type: string
          format: object-id
          nullable: true
        order_ref:
          description: The human-readable reference of the parent order.
          type: string
          nullable: true
          example: TRY00
        item_cost:
          description: |
            The amount paid for the voucher itself (which may differ from
            the voucher's face value for promotional pricing) in the
            smallest unit of the order currency.
          type: integer
          nullable: true
          example: 5000
        submitted_at:
          description: When the parent order was submitted.
          type: string
          format: date-time
          nullable: true
      required:
        - id
        - customer_id
        - order_ref
        - item_cost
        - submitted_at
    VoucherCodeRedemption:
      title: VoucherCodeRedemption
      description: A single redemption recorded against a voucher code.
      type: object
      additionalProperties: false
      properties:
        payment_id:
          description: The ID of the `Payment` that records this redemption.
          type: string
          format: object-id
        amount:
          description: |
            The amount redeemed against the voucher in this transaction,
            in the smallest unit of the voucher's currency.
          type: integer
          example: 2500
        refunded_amount:
          description: |
            Of `amount`, the portion that was later refunded back to the
            voucher (restoring its balance).
          type: integer
          example: 0
        paid_at:
          description: When the redemption was applied.
          type: string
          format: date-time
          nullable: true
        payable_id:
          description: The ID of the object the redemption was applied to.
          type: string
          format: object-id
        order_ref:
          description: |
            If the redemption was against an order, the human-readable
            order reference.
          type: string
      required:
        - payment_id
        - amount
        - refunded_amount
        - paid_at
        - payable_id
    VoucherCode:
      title: VoucherCode
      description: |
        A single issued instance of a `VoucherType` — the redeemable code,
        its monetary balance, validity dates, recipient, and delivery
        metadata. `VoucherCode`s are produced by the basket pipeline when
        a voucher is purchased, and consumed when the code is presented as
        payment against a future order.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the voucher code.
          type: string
          format: object-id
        code:
          description: |
            The redemption code itself. Display this to the customer or
            recipient — they will quote it back to redeem against an
            order.
          type: string
          example: ABC123XYZ
        status:
          description: |
            The lifecycle state of the voucher. `unredeemed` is the
            starting state; vouchers transition to `partially_redeemed`,
            `redeemed`, `expired`, or `revoked` over their life.
          type: string
          enum:
            - unredeemed
            - partially_redeemed
            - redeemed
            - revoked
            - expired
        valid_from_date:
          description: The first date on which the voucher can be redeemed.
          type: string
          format: date-time
          example: '2026-01-01T00:00:00+00:00'
        valid_to_date:
          description: |
            The last date on which the voucher can be redeemed. Updating
            this date past today on an `expired` voucher will move it back
            to `unredeemed` (or `partially_redeemed` if it has prior
            redemptions).
          type: string
          format: date-time
          nullable: true
          example: '2027-01-01T00:00:00+00:00'
        amount_type:
          description: |
            Whether the voucher represents a fixed `cash` value or
            discounts the order it is redeemed against to zero
            (`discount_to_zero`).
          type: string
          enum:
            - cash
            - discount_to_zero
        amount:
          description: |
            The face value of the voucher, in the smallest unit of the
            voucher's currency (e.g. pence for GBP).
          type: integer
          example: 5000
        balance:
          description: |
            The remaining balance of the voucher, in the smallest unit of
            the voucher's currency. `discount_to_zero` vouchers report
            their balance as zero once redeemed.
          type: integer
          example: 2500
        currency:
          $ref: '#/components/schemas/properties_currency'
        value:
          description: |
            Alias of `amount`, retained for backwards compatibility with
            older clients.
          type: integer
          example: 5000
        partially_redeemable:
          description: |
            Whether the voucher can be redeemed across multiple
            transactions. `discount_to_zero` vouchers are never partially
            redeemable.
          type: boolean
          example: true
        uses_total:
          description: |
            For multi-use `discount_to_zero` codes only: the total number of
            redemptions the code allows. `null` when the parent `VoucherType`
            has `quantity` of `null` or `1`, and for all `cash` vouchers.
          type: integer
          nullable: true
          example: 7
        uses_remaining:
          description: |
            For multi-use `discount_to_zero` codes only: how many redemptions
            are still available. Decrements by 1 each time the code is
            successfully redeemed; restored by 1 if a redemption is refunded.
            `null` when the parent `VoucherType` has `quantity` of `null` or
            `1`, and for all `cash` vouchers.
          type: integer
          nullable: true
          example: 5
        imported:
          description: |
            Whether this voucher was imported from a previous system
            rather than issued through Trybe.
          type: boolean
          example: false
        fulfillment_status:
          description: |
            Tracks physical fulfilment for vouchers that need posting.
            Common values are `needs_dispatching`, `dispatched`, and
            `not_required` for digital deliveries.
          type: string
          nullable: true
          example: needs_dispatching
        voucher_type:
          $ref: '#/components/schemas/VoucherCodeVoucherTypeRef'
        recipient:
          $ref: '#/components/schemas/VoucherCodeRecipient'
        delivery:
          $ref: '#/components/schemas/VoucherCodeDelivery'
        order:
          $ref: '#/components/schemas/VoucherCodeOrderRef'
        redemptions:
          description: |
            Per-redemption breakdown — present on the `getVoucherCode`
            response, omitted from list responses for performance.
          type: array
          items:
            $ref: '#/components/schemas/VoucherCodeRedemption'
        created_at:
          $ref: '#/components/schemas/createdAt'
        issued_at:
          description: |
            When the voucher was issued to the customer. Vouchers that
            have been purchased but not yet issued (e.g. scheduled for a
            future delivery date) will have `issued_at` set to `null`.
          type: string
          format: date-time
          nullable: true
          example: '2026-01-02T09:00:00+00:00'
      required:
        - id
        - code
        - status
        - valid_from_date
        - valid_to_date
        - amount_type
        - amount
        - balance
        - currency
        - value
        - partially_redeemable
        - uses_total
        - uses_remaining
        - imported
        - fulfillment_status
        - voucher_type
        - recipient
        - delivery
        - order
        - created_at
        - issued_at
    ListVoucherCodesResponse:
      title: ListVoucherCodesResponse
      allOf:
        - $ref: '#/components/schemas/Pagination'
        - title: ListVoucherCodesResponseData
          type: object
          additionalProperties: false
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/VoucherCode'
          required:
            - data
    BulkCreateVoucherCodeItem:
      title: BulkCreateVoucherCodeItem
      description: A single voucher code to import.
      type: object
      additionalProperties: false
      properties:
        code:
          description: |
            The redemption code. Must be alphanumeric, distinct within this
            request, and unique within the organisation.
          type: string
          pattern: ^[a-zA-Z0-9]+$
          example: GIFTABC123
        amount:
          description: |
            The face value of the voucher as a decimal number (e.g. `50.00`
            for £50). Minimum `0.01`.
          type: number
          format: float
          minimum: 0.01
          example: 50
        balance:
          description: |
            The current remaining balance as a decimal number. Must be
            between `0` and `amount`. Defaults to `amount` when omitted.
          type: number
          format: float
          minimum: 0
          example: 50
        voucher_type_id:
          description: The ID of the `VoucherType` to associate the voucher code with.
          type: string
          format: object-id
        valid_until:
          description: |
            The expiry date for the voucher in `Y-m-d` format. Omit to
            create a voucher with no expiry.
          type: string
          format: date
          nullable: true
          example: '2027-12-31'
        revenue_amount:
          description: |
            Optional revenue value override in decimal form. When provided
            this is used for revenue reporting instead of `amount`.
          type: number
          format: float
          nullable: true
          minimum: 0
          example: 50
      required:
        - code
        - amount
        - voucher_type_id
    BulkCreateVoucherCodesRequest:
      title: BulkCreateVoucherCodesRequest
      description: Request body for `actionBulkCreateVoucherCodes`.
      type: object
      additionalProperties: false
      properties:
        vouchers:
          description: The voucher codes to import. Must contain at least one item.
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/BulkCreateVoucherCodeItem'
      required:
        - vouchers
    UpdateVoucherCode:
      title: UpdateVoucherCode
      description: |
        Body for `updateVoucherCode`. Every field is optional; pass only
        the fields you want to change.
      type: object
      additionalProperties: false
      properties:
        valid_to_date:
          description: |
            Extend or shorten the voucher's expiry. Setting a date in the
            past on an active voucher will move it to `expired`; setting a
            future date on an `expired` voucher will move it back to
            `unredeemed` (or `partially_redeemed` if there are prior
            redemptions). Must be an RFC 3339 timestamp.
          type: string
          format: date-time
          example: '2027-01-01T23:59:59+00:00'
        fulfillment_status:
          description: |
            Override the fulfilment status — typically used to mark a
            physical voucher as `dispatched` after posting.
          type: string
          example: dispatched
    schemas_Category:
      title: Category
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the category.
        name:
          type: string
          description: The name of the category.
          example: Massages
        voucher_applicable:
          type: boolean
      required:
        - id
        - name
        - voucher_applicable
    Contraindication:
      title: AppointmentTypeContraindication
      type: object
      additionalProperties: false
      properties:
        condition:
          type: string
          enum:
            - blood_pressure
            - cancer
            - diabetes
            - epilepsy
            - pregnancy
        indication:
          type: string
          enum:
            - conditional
            - controlled
            - 'no'
            - 'yes'
        notes:
          type: string
      required:
        - condition
        - indication
    OfferingIdentifier:
      title: OfferingIdentifier
      type: object
      additionalProperties: false
      properties:
        offering_id:
          type: string
          format: mongo-id
          description: The ID of the offering.
        offering_name:
          type: string
          description: The name of the offering.
          example: Twilight massage
        offering_type:
          $ref: '#/components/schemas/OfferingType'
      required:
        - offering_id
        - offering_name
        - offering_type
    customerCancellationPermitted:
      type: string
      enum:
        - allowed
        - disallowed
        - unpaid
      example: allowed
    customerReschedulePermitted:
      type: string
      nullable: true
      description: |
        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).
      enum:
        - allowed
        - disallowed
        - unpaid
      example: allowed
    MembershipBookingWindow:
      title: MembershipBookingWindow
      type: object
      additionalProperties: false
      required:
        - membership_type_id
        - max_advance_bookings_interval
        - min_advance_bookings_interval
      properties:
        membership_type_id:
          type: string
          format: uuid
          description: The ID of the membership type this booking window applies to.
        max_advance_bookings_interval:
          type: string
          description: The maximum time before a booking's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2W
        min_advance_bookings_interval:
          type: string
          description: The minimum time before a booking's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2D
    PriceRule:
      title: AppointmentTypePriceRule
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        appointment_type_id:
          type: string
          format: object-id
        date_from:
          type: string
          format: date
          nullable: true
        date_to:
          type: string
          format: date
          nullable: true
        duration:
          type: integer
          nullable: true
        price:
          type: integer
        time_from:
          type: string
          nullable: true
          example: '12:00'
        time_to:
          type: string
          nullable: true
          example: '16:00'
        weekdays:
          type: array
          items:
            type: string
      required:
        - id
        - appointment_type_id
        - date_from
        - date_to
        - duration
        - price
        - time_from
        - time_to
        - weekdays
    YieldManagement:
      title: YieldManagement
      description: |
        Raw yield-only price guardrails for an eligible offering. Money values use
        integer minor units, matching `standard_price`.

        The nested object is optional on create, update, and copy requests. When
        omitted, the existing configuration is preserved. When supplied, it
        replaces the complete yield-management configuration atomically.

        Writes require the offering-pricing permission and the
        `advanced_yield_management` feature. If the feature is unavailable,
        supplying this object returns a `422` validation error. Existing
        configuration remains readable when the feature is unavailable.
      type: object
      additionalProperties: false
      properties:
        price_floor:
          type: integer
          minimum: 0
          nullable: true
          description: |
            The lowest price a yield adjustment may produce, in integer minor
            units. An explicit value requires `standard_price` and must be less
            than or equal to it. `null` dynamically inherits the offering's
            current Standard price without persisting a copy, allowing a later
            Standard-price change to update the effective floor automatically.
          example: 4000
        price_ceiling:
          type: integer
          minimum: 0
          nullable: true
          description: |
            The highest price a yield adjustment may produce, in integer minor
            units. An explicit value requires `standard_price` and must be greater
            than or equal to it. `null` leaves the ceiling unbounded.
          example: 6000
        reduction_advance_interval:
          type: string
          nullable: true
          description: |
            How far ahead of a slot a rule that lowers the price may start applying,
            as an ISO-8601 duration. Required before a negative-adjustment yield rule
            can be saved, and cannot be cleared while one still applies. `null` means
            the offering has no price reductions configured.
          example: P14D
      required:
        - price_floor
        - price_ceiling
        - reduction_advance_interval
    Tag:
      title: Tag
      type: object
      additionalProperties: false
      required:
        - id
        - name
        - organisation_id
      properties:
        id:
          type: string
        name:
          type: string
        organisation_id:
          type: string
    visibility:
      description: The visibility status of the product.
      type: string
      enum:
        - public
        - link_only
        - private
      example: public
    deletedAt:
      description: When then resource was deleted.
      type: string
      format: date-time
      nullable: true
      example: '2025-02-04T12:00:00+01:00'
    AppointmentType:
      title: AppointmentType
      description: An `AppointmentType` offering model.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        allocate_multi_capacity_rooms:
          type: boolean
        canada_rmt_eligible:
          type: boolean
        categories:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Category'
        category_ids:
          type: array
          items:
            type: string
            format: object-id
        contraindications:
          type: array
          items:
            $ref: '#/components/schemas/Contraindication'
        cross_sell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        currency:
          $ref: '#/components/schemas/properties_currency'
        customer_cancellation_min_duration:
          type: string
          nullable: true
          example: P7D
        customer_cancellation_permitted:
          $ref: '#/components/schemas/customerCancellationPermitted'
        customer_reschedule_min_duration:
          type: string
          nullable: true
          example: P7D
        customer_reschedule_permitted:
          $ref: '#/components/schemas/customerReschedulePermitted'
        customers_only:
          type: boolean
        description:
          type: string
        durations:
          type: array
          items:
            type: integer
        end_buffer:
          type: integer
          nullable: true
        enquiries_enabled:
          type: boolean
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        equipment_ids:
          type: array
          items:
            type: string
            format: object-id
        image:
          $ref: '#/components/schemas/Media'
          nullable: true
        include_pricing_on_calendar:
          type: boolean
        max_advance_bookings_interval:
          type: string
          nullable: true
        max_guests:
          type: integer
        practitioners_per_guest:
          type: integer
          description: The number of practitioners that are required for each guest to be booked for this appointment type
        max_per_basket:
          type: integer
          nullable: true
        max_per_guest:
          type: integer
          nullable: true
        members_only:
          type: boolean
        membership_booking_windows:
          type: array
          items:
            $ref: '#/components/schemas/MembershipBookingWindow'
        membership_booking_windows_enabled:
          type: boolean
        meta:
          title: AppointmentTypeMeta
          type: object
          additionalProperties: false
          properties:
            description:
              type: string
              nullable: true
            title:
              type: string
              nullable: true
          required:
            - description
            - title
        min_advance_bookings_interval:
          type: string
          nullable: true
        min_guests:
          type: integer
        name:
          type: string
        offered_online:
          type: boolean
        permitted_membership_type_ids:
          type: array
          items:
            type: string
            format: object-id
        private:
          type: boolean
        product_code:
          type: string
          nullable: true
        practitioner_ids:
          type: array
          items:
            type: string
            format: object-id
        price_rules:
          type: array
          items:
            $ref: '#/components/schemas/PriceRule'
        related_retail_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        revenue_centre:
          type: string
          nullable: true
        room_ids:
          type: array
          items:
            type: string
            format: object-id
        shop_practitioner_selection:
          type: string
          nullable: true
          enum:
            - by_name
            - by_gender
        site_ids:
          type: array
          items:
            type: string
            format: object-id
        yield_management:
          $ref: '#/components/schemas/YieldManagement'
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this appointment type, in the smallest
            currency unit (e.g. pence). `null` if a standard price hasn't
            been configured — this is distinct from a price of zero.
          example: 5000
        start_time_interval:
          type: integer
        tag_ids:
          type: array
          items:
            type: string
            format: object-id
        tags:
          type: array
          items:
            $ref: '#/components/schemas/Tag'
        upsell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        visibility:
          $ref: '#/components/schemas/visibility'
        deleted_at:
          $ref: '#/components/schemas/deletedAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - allocate_multi_capacity_rooms
        - canada_rmt_eligible
        - categories
        - category_ids
        - contraindications
        - cross_sell_offerings
        - currency
        - customer_cancellation_min_duration
        - customer_cancellation_permitted
        - customer_reschedule_min_duration
        - customer_reschedule_permitted
        - customers_only
        - description
        - durations
        - end_buffer
        - enquiries_enabled
        - equipment_ids
        - external_id
        - include_pricing_on_calendar
        - max_advance_bookings_interval
        - max_guests
        - practitioners_per_guest
        - max_per_basket
        - max_per_guest
        - members_only
        - membership_booking_windows
        - membership_booking_windows_enabled
        - meta
        - min_advance_bookings_interval
        - min_guests
        - name
        - offered_online
        - practitioner_ids
        - price_rules
        - private
        - product_code
        - related_retail_offerings
        - revenue_centre
        - room_ids
        - shop_practitioner_selection
        - site_ids
        - standard_price
        - yield_management
        - start_time_interval
        - tag_ids
        - tags
        - visibility
        - upsell_offerings
        - deleted_at
        - updated_at
    AvailabilityRule:
      title: AvailabilityRule
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the availability rule.
        date_from:
          type: string
          format: date
          description: The start of the rule period.
          example: '2021-02-15'
        date_to:
          type: string
          format: date
          description: The end of the rule period.
          example: '2021-02-15'
        is_available:
          type: boolean
          description: Whether the resource is available during this period. Any `false` rules will override `true` rules.
        max_duration:
          type: integer
          description: Maximum number of minutes.
        min_duration:
          type: integer
          description: Minimum number of minutes.
        time_from:
          type: string
          description: The daily start time of the time period, in 24 hour format.
          example: '11:00'
        time_to:
          type: string
          description: The daily end time of the time period, in 24 hour format.
          example: '17:00'
        weekdays:
          type: array
          description: The weekdays this rule applies to.
          items:
            type: string
      required:
        - id
        - date_from
        - date_to
        - is_available
        - time_from
        - time_to
    schema:
      title: UpdateAppointmentTypeAvailabilityRule
      type: object
      additionalProperties: false
      properties:
        is_available:
          type: boolean
          description: Whether the window is bookable. `false` rules override `true` rules.
        date_from:
          type: string
          format: date
          nullable: true
          description: First date this rule applies (inclusive).
          example: '2026-06-01'
        date_to:
          type: string
          format: date
          nullable: true
          description: Last date this rule applies (inclusive).
          example: '2026-08-31'
        time_from:
          type: string
          nullable: true
          description: Daily start time in `HH:MM`.
          example: '10:00'
        time_to:
          type: string
          nullable: true
          description: Daily end time in `HH:MM`.
          example: '18:00'
        min_duration:
          type: integer
          minimum: 1
          nullable: true
          description: Match only for durations ≥ this many minutes.
          example: 30
        max_duration:
          type: integer
          minimum: 1
          nullable: true
          description: Match only for durations ≤ this many minutes.
          example: 120
        weekdays:
          type: array
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
      required:
        - is_available
    schemas_PriceRule:
      type: object
      title: PriceRule
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the price rule.
        price:
          type: integer
          description: The price applied by this rule
          example: 4800
        date_from:
          type: string
          format: date
          nullable: true
          description: The first date this rule should be applied.
        date_to:
          type: string
          format: date
          nullable: true
          description: The last date this rule should be applied.
        weekdays:
          type: array
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
          description: The weekdays this rule should be applied.
        time_from:
          type: string
          nullable: true
          description: This rule will be applied to bookings starting on or after this time.
        time_to:
          type: string
          nullable: true
          description: This rule will be applied to bookings starting before this time.
        duration:
          type: integer
          nullable: true
          description: This rule will be applied to bookings of this duration.
    OfferingLocaleStrings:
      title: OfferingLocaleStrings
      description: Localised strings for an offering type in a non-English locale, covering name, description, and SEO meta fields.
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        meta_title:
          type: string
          nullable: true
        meta_description:
          type: string
          nullable: true
      required:
        - name
        - description
        - meta_title
        - meta_description
    schemas_PriceRule-2:
      title: AreaBookingTypePriceRule
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        area_booking_type_id:
          type: string
          format: object-id
        date_from:
          type: string
          format: date
          nullable: true
        date_to:
          type: string
          format: date
          nullable: true
        max_duration:
          type: integer
          nullable: true
        price:
          type: integer
        time_from:
          type: string
          nullable: true
          example: '12:00'
        time_to:
          type: string
          nullable: true
          example: '16:00'
        weekdays:
          type: array
          items:
            type: string
      required:
        - id
        - area_booking_type_id
        - date_from
        - date_to
        - max_duration
        - price
        - time_from
        - time_to
        - weekdays
    AreaBookingType:
      title: AreaBookingType
      description: An `AreaBookingType` offering model.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        area_ids:
          type: array
          items:
            type: string
            format: object-id
        availability_rules:
          type: array
          items:
            $ref: '#/components/schemas/AvailabilityRule'
        categories:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Category'
        category_ids:
          type: array
          items:
            type: string
            format: object-id
        cross_sell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        currency:
          $ref: '#/components/schemas/properties_currency'
        customer_cancellation_min_duration:
          type: string
          nullable: true
          example: P7D
        customer_cancellation_permitted:
          $ref: '#/components/schemas/customerCancellationPermitted'
        customer_reschedule_min_duration:
          type: string
          nullable: true
          example: P7D
        customer_reschedule_permitted:
          $ref: '#/components/schemas/customerReschedulePermitted'
        customers_only:
          type: boolean
        description:
          type: string
        duration_interval:
          type: integer
        end_buffer:
          type: integer
          nullable: true
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        image:
          $ref: '#/components/schemas/Media'
        include_pricing_on_calendar:
          type: boolean
        max_advance_bookings_interval:
          type: string
          nullable: true
        max_baskets:
          type: integer
          nullable: true
        max_duration:
          type: integer
          nullable: true
        max_guests:
          type: integer
          nullable: true
        max_per_basket:
          type: integer
          nullable: true
        max_per_guest:
          type: integer
          nullable: true
        members_only:
          type: boolean
        membership_booking_windows:
          type: array
          items:
            $ref: '#/components/schemas/MembershipBookingWindow'
        membership_booking_windows_enabled:
          type: boolean
        meta:
          title: AreaBookingTypeMeta
          type: object
          additionalProperties: false
          properties:
            description:
              type: string
              nullable: true
            title:
              type: string
              nullable: true
          required:
            - description
            - title
        min_advance_bookings_interval:
          type: string
          nullable: true
        min_duration:
          type: integer
          nullable: true
        min_guests:
          type: integer
          nullable: true
        name:
          type: string
        offered_online:
          type: boolean
        permitted_membership_type_ids:
          type: array
          items:
            type: string
            format: object-id
        price_rules:
          type: array
          items:
            $ref: '#/components/schemas/schemas_PriceRule-2'
        private:
          type: boolean
        product_code:
          type: string
          nullable: true
        related_retail_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        revenue_centre:
          type: string
          nullable: true
        site_id:
          type: string
          format: uuid
        yield_management:
          $ref: '#/components/schemas/YieldManagement'
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this area booking type, in the smallest
            currency unit (e.g. pence). `null` if a standard price hasn't
            been configured — this is distinct from a price of zero.
          example: 5000
        start_time_interval:
          type: integer
        upsell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        visibility:
          $ref: '#/components/schemas/visibility'
        deleted_at:
          $ref: '#/components/schemas/deletedAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - area_ids
        - availability_rules
        - categories
        - category_ids
        - cross_sell_offerings
        - currency
        - customer_cancellation_min_duration
        - customer_cancellation_permitted
        - customer_reschedule_min_duration
        - customer_reschedule_permitted
        - customers_only
        - description
        - duration_interval
        - end_buffer
        - external_id
        - include_pricing_on_calendar
        - max_advance_bookings_interval
        - max_baskets
        - max_duration
        - max_guests
        - max_per_basket
        - max_per_guest
        - members_only
        - membership_booking_windows
        - membership_booking_windows_enabled
        - meta
        - min_advance_bookings_interval
        - min_duration
        - min_guests
        - name
        - offered_online
        - price_rules
        - private
        - product_code
        - related_retail_offerings
        - revenue_centre
        - site_id
        - standard_price
        - yield_management
        - start_time_interval
        - upsell_offerings
        - visibility
        - deleted_at
        - updated_at
    application~1json-schema:
      title: UpdateAreaBookingTypeAvailabilityRule
      type: object
      additionalProperties: false
      properties:
        is_available:
          type: boolean
          description: Whether the window is bookable. `false` rules override `true` rules.
        date_from:
          type: string
          format: date
          nullable: true
          description: First date this rule applies (inclusive).
          example: '2026-06-01'
        date_to:
          type: string
          format: date
          nullable: true
          description: Last date this rule applies (inclusive).
          example: '2026-08-31'
        time_from:
          type: string
          nullable: true
          description: Daily start time in `HH:MM`.
          example: '10:00'
        time_to:
          type: string
          nullable: true
          description: Daily end time in `HH:MM`.
          example: '18:00'
        min_duration:
          type: integer
          minimum: 1
          description: Match only for durations ≥ this many minutes.
          example: 60
        max_duration:
          type: integer
          minimum: 1
          description: Match only for durations ≤ this many minutes.
          example: 480
        weekdays:
          type: array
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
      required:
        - is_available
    BasketCheckoutConfig:
      title: BasketCheckoutConfig
      type: object
      additionalProperties: false
      properties:
        terms:
          type: array
          description: |
            Terms and conditions that must be presented (and where
            applicable accepted) by the customer before submitting the
            basket.
          items:
            title: BasketCheckoutConfigTerm
            type: object
            additionalProperties: true
            properties:
              id:
                type: string
                format: object-id
                description: Unique identifier of the terms entry.
              name:
                type: string
                description: Short label for the terms entry (e.g. "Cancellation Policy").
              content:
                type: string
                description: The full terms text. May contain HTML.
              source:
                type: string
                description: |
                  Where these terms originated — typically one of `site`,
                  `offering`, or `basket`.
        contraindications:
          type: array
          description: |
            Clinical contraindications attached to appointment offerings
            in the basket. The customer must positively confirm none of
            these apply before the basket can be submitted.
          items:
            title: BasketCheckoutConfigContraindication
            type: object
            additionalProperties: true
            properties:
              id:
                type: string
                format: object-id
                description: Unique identifier of the contraindication.
              name:
                type: string
                description: Short label for the contraindication.
              description:
                type: string
                description: Longer explanation of the contraindication.
              indication:
                type: string
                description: |
                  Whether the offering is `no` (never bookable) or
                  `conditional` (bookable with acknowledgement) when the
                  customer confirms this contraindication.
              offering_id:
                type: string
                format: object-id
                description: ID of the offering that introduced this contraindication.
        voucher_payment_enabled:
          type: boolean
          description: |
            `true` when the site has an external voucher integration
            configured, meaning customers can pay (in whole or in part)
            with third-party voucher codes at checkout.
      required:
        - terms
        - contraindications
        - voucher_payment_enabled
    IntakeFormLink:
      type: object
      title: IntakeFormLink
      additionalProperties: false
      properties:
        intake_form_url:
          type: string
          description: |
            The URL to the intake form.
            If there are no intake forms to complete for this order, this will be `null`.
          example: https://example.com/intake-form?id=123
          nullable: true
        intake_form_complete:
          type: boolean
          description: Whether the intake forms are complete for all guests in the basket.
          example: true
      required:
        - intake_form_url
        - intake_form_complete
    Zone:
      title: Zone
      description: |
        A `Zone` is a logical area within a site used to group resources
        for reservations and reporting (e.g. `Pool Deck`, `Sun Loungers`,
        `Garden Cabanas`). Zones are referenced by area-booking types,
        practitioners, and other bookable resources to constrain where
        they live or work.

        Zones are scoped to a single site; the same zone name may exist
        independently at multiple sites.
      type: object
      additionalProperties: false
      required:
        - id
        - name
        - organisation_id
        - site_id
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the zone.
          example: 5f1234567890abcdef123456
        name:
          type: string
          description: |
            Display name for the zone, shown wherever zones are listed or
            filtered. Plain text only.
          example: Pool Deck
        organisation_id:
          type: string
          format: uuid
          description: |
            ID of the organisation that owns this zone. Inherited from the
            site on create.
          example: 22222222-2222-2222-2222-222222222222
        site_id:
          type: string
          format: uuid
          description: ID of the site this zone belongs to.
          example: 11111111-1111-1111-1111-111111111111
    BookableArea:
      title: BookableArea
      description: |
        A `BookableArea` is a physical area that can be booked by guests
        via an `AreaBookingType` (e.g. a hot tub, a cabana, a treatment
        pod). Bookable areas have a `capacity` (number of simultaneous
        bookings) and an availability schedule made up of one or more
        `AvailabilityRule`s.
      type: object
      additionalProperties: false
      required:
        - id
        - organisation_id
        - site_id
        - name
        - description
        - capacity
        - availability_rules
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier of the bookable area.
          example: 5dcb47800000000000000000
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation the bookable area belongs to.
          example: 0193b6e0-3b56-7000-9f50-9d3d5e2c1111
        site_id:
          type: string
          format: uuid
          description: |
            ID of the site the bookable area belongs to. A bookable area
            is scoped to exactly one site.
          example: 0193b6e0-3b56-7000-9f50-9d3d5e2c2222
        name:
          type: string
          description: Display name for the bookable area. Shown to staff and customers.
          example: Hot Tub 1
        description:
          type: string
          nullable: true
          description: Long-form description of the bookable area.
          example: |
            Private rooftop hot tub for up to four guests. 38°C, sunset
            views over the gardens.
        capacity:
          type: integer
          minimum: 1
          description: |
            Maximum number of simultaneous bookings. `1` means
            exclusive-use; values > 1 allow shared occupancy.
          example: 4
        availability_rules:
          type: array
          description: |
            The `AvailabilityRule`s currently configured on this area.
            These determine when the area is bookable. Manage them via
            the `/shop/bookable-areas/{bookableAreaId}/availability-rules`
            endpoints.
          items:
            $ref: '#/components/schemas/AvailabilityRule'
        zones:
          type: array
          description: |
            Hydrated `Zone` records this bookable area belongs to. Zones
            group areas in the floor plan for spatial constraints.
          items:
            $ref: '#/components/schemas/Zone'
    content-application~1json-schema:
      title: UpdateBookableArea
      type: object
      additionalProperties: false
      required:
        - name
        - capacity
      properties:
        name:
          type: string
          description: New display name for the bookable area.
          example: Hot Tub 1
        description:
          type: string
          nullable: true
          description: |
            Replacement long-form description shown to customers on
            the shopfront. Markdown is rendered. Pass null to clear.
          example: Heated 4-person hot tub with hydrotherapy jets, available year-round.
        capacity:
          type: integer
          minimum: 1
          description: |
            New capacity. Lowering capacity doesn't cancel existing
            bookings — they keep their slot.
          example: 4
        zone_ids:
          type: array
          description: Zones the area belongs to. Filtered to the area's site.
          items:
            type: string
            format: object-id
    UpdateBookableAreaAvailabilityRule-content-application~1json-schema:
      title: UpdateBookableAreaAvailabilityRule
      type: object
      additionalProperties: false
      required:
        - is_available
      properties:
        is_available:
          type: boolean
          description: Whether the window is bookable. `false` rules override `true` rules.
        date_from:
          type: string
          format: date
          nullable: true
          description: First date this rule applies (inclusive).
          example: '2026-06-01'
        date_to:
          type: string
          format: date
          nullable: true
          description: Last date this rule applies (inclusive).
          example: '2026-08-31'
        time_from:
          type: string
          nullable: true
          description: Daily start time in `HH:MM`.
          example: '10:00'
        time_to:
          type: string
          nullable: true
          description: Daily end time in `HH:MM`.
          example: '18:00'
        weekdays:
          type: array
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
    schemas_PriceRule-3:
      title: CourseTypePriceRule
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        date_from:
          type: string
          format: date
          nullable: true
        date_to:
          type: string
          format: date
          nullable: true
        price:
          type: integer
      required:
        - id
        - date_from
        - date_to
        - price
    CourseType:
      title: CourseType
      description: A `CourseType` offering type.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        availability_rules:
          type: array
          items:
            $ref: '#/components/schemas/AvailabilityRule'
        category_ids:
          type: array
          items:
            type: string
            format: object-id
        coupon_id:
          type: string
          format: object-id
          nullable: true
        credits_validity_interval:
          type: string
          nullable: true
          example: P7D
        cross_sell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        currency:
          $ref: '#/components/schemas/properties_currency'
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        customers_only:
          type: boolean
        description:
          type: string
        image:
          $ref: '#/components/schemas/Media'
        members_only:
          type: boolean
        meta:
          title: CourseTypeMeta
          type: object
          additionalProperties: false
          properties:
            description:
              type: string
              nullable: true
            title:
              type: string
              nullable: true
          required:
            - description
            - title
        name:
          type: string
        offered_online:
          type: boolean
        offering_id:
          type: string
          format: object-id
          nullable: true
        offering_type:
          $ref: '#/components/schemas/OfferingType'
          nullable: true
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        permitted_membership_type_ids:
          type: array
          items:
            type: string
            format: object-id
        price_rules:
          type: array
          items:
            $ref: '#/components/schemas/schemas_PriceRule-3'
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this course type, in the smallest
            currency unit (e.g. pence). `null` if a standard price hasn't
            been configured — this is distinct from a price of zero.
          example: 5000
        private:
          type: boolean
        product_code:
          type: string
          nullable: true
        quantity:
          type: integer
        related_retail_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        revenue_centre:
          type: string
          nullable: true
        site_id:
          type: string
          format: uuid
        upsell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        visibility:
          $ref: '#/components/schemas/visibility'
        deleted_at:
          $ref: '#/components/schemas/deletedAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - availability_rules
        - category_ids
        - coupon_id
        - credits_validity_interval
        - cross_sell_offerings
        - currency
        - customers_only
        - description
        - external_id
        - members_only
        - meta
        - name
        - offered_online
        - offering_id
        - offering_type
        - offerings
        - price_rules
        - standard_price
        - private
        - product_code
        - quantity
        - related_retail_offerings
        - revenue_centre
        - site_id
        - upsell_offerings
        - visibility
        - deleted_at
        - updated_at
    UpdateCourseTypeAvailabilityRule-content-application~1json-schema:
      title: UpdateCourseTypeAvailabilityRule
      type: object
      additionalProperties: false
      properties:
        is_available:
          type: boolean
          description: Whether the rule opens or closes the window.
          example: true
        date_from:
          type: string
          format: date
          nullable: true
          description: First date this rule applies.
          example: '2026-06-01'
        date_to:
          type: string
          format: date
          nullable: true
          description: Last date this rule applies. Must be ≥ date_from.
          example: '2026-08-31'
      required:
        - is_available
    CustomerLabel:
      type: object
      title: CustomerLabel
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier for the label.
        name:
          type: string
          description: The name of the label.
          example: VIP
        color:
          type: string
          description: The color associated with the label.
          example: '#FF5733'
      required:
        - id
        - name
        - color
    CustomerSearchResult:
      type: object
      title: CustomerSearchResult
      additionalProperties: false
      properties:
        id:
          type: string
          description: The unique identifier for the customer.
          example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        first_name:
          type: string
          description: The first name of the customer.
          example: Jane
        last_name:
          type: string
          description: The last name of the customer.
          example: Smith
        email:
          type: string
          format: email
          description: The email address of the customer.
          example: jane.smith@example.com
        sources:
          type: array
          description: The sources where the customer was found.
          items:
            type: string
            example: trybe
        labels:
          type: array
          description: The Trybe labels associated with the customer.
          items:
            $ref: '#/components/schemas/CustomerLabel'
      required:
        - id
        - first_name
        - last_name
        - email
        - sources
        - labels
    CustomerSearchResultsSource:
      type: object
      title: CustomerSearchResultsSource
      additionalProperties: false
      properties:
        key:
          type: string
          description: The source of the customers.
          example: trybe
        name:
          type: string
          description: The name of the source.
          example: Trybe
        status:
          type: string
          description: The status of attempt to search for customers from this source.
          example: success
        message:
          type: string
          description: An optional message about the source.
          example: Trybe did not respond in time.
          nullable: true
      required:
        - key
        - name
        - status
    CustomerSearchMeta:
      type: object
      title: CustomerSearchMeta
      additionalProperties: false
      properties:
        sources:
          type: array
          description: An array of sources that were queried during the search.
          items:
            $ref: '#/components/schemas/CustomerSearchResultsSource'
      required:
        - sources
    CustomerStatsTotals:
      type: object
      title: CustomerStatsTotals
      additionalProperties: false
      properties:
        total_order_value:
          type: integer
          description: The total value of all submitted orders for this customer.
          example: 38500
        average_order_value:
          type: integer
          description: This customer's average order value.
          example: 19250
        num_orders:
          type: integer
          description: The number of orders this customer has made.
          example: 2
      required:
        - total_order_value
        - average_order_value
        - num_orders
    schemas_CustomerSummary:
      title: CustomerSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the customer.
        email:
          type: string
          description: The email of the customer.
          example: jane@example.com
          nullable: true
        first_name:
          type: string
          description: The first name of the customer.
          example: Jane
          nullable: true
        last_name:
          type: string
          description: The last name of the customer.
          example: Jones
          nullable: true
      required:
        - id
        - email
        - first_name
        - last_name
    SalesChannel:
      title: SalesChannel
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the sales channel.
        name:
          type: string
          description: The name of the sales channel.
          example: Website
    OrderTotals:
      title: CustomerStatsOrderTotals
      type: object
      additionalProperties: false
      properties:
        subtotal:
          type: integer
          description: The total cost of the order without order-level discounts, tip and service charge.
          example: 15000
        order_discount:
          type: integer
          description: The total amount of order-level discount applied to the order.
          example: 0
        total:
          type: integer
          description: The total cost of the order after discount, tip and service charge.
          example: 15000
    SiteSummary:
      title: SiteSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the site
        name:
          type: string
          description: The name of the site
          example: Palm Tree Spa
      required:
        - id
        - name
    OrderSummary:
      title: CustomerStatsOrderSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the order.
        order_ref:
          type: string
          description: The order ref of the order.
        status:
          type: string
          description: The status of the order.
          enum:
            - submitted
            - settled
            - cancelled
            - no_show
        num_items:
          type: integer
          description: The number of items in the order.
          example: 2
        customer:
          $ref: '#/components/schemas/schemas_CustomerSummary'
        sales_channel:
          $ref: '#/components/schemas/SalesChannel'
          nullable: true
        totals:
          $ref: '#/components/schemas/OrderTotals'
        submitted_at:
          type: string
          format: date-time
          description: The date and time the order was submitted
        site:
          $ref: '#/components/schemas/SiteSummary'
      required:
        - id
        - order_ref
        - status
        - customer
        - sales_channel
        - totals
        - submitted_at
        - site
    CustomerStats:
      title: CustomerStats
      type: object
      additionalProperties: false
      properties:
        totals:
          type: object
          $ref: '#/components/schemas/CustomerStatsTotals'
        recent_orders:
          type: array
          items:
            $ref: '#/components/schemas/OrderSummary'
      required:
        - totals
        - recent_orders
    CustomerStatsMeta:
      title: CustomerStatsMeta
      type: object
      additionalProperties: false
      properties:
        currency:
          type: string
          description: The currency used for the customer stats
          example: gbp
      required:
        - currency
    Equipment:
      title: Equipment
      description: |
        `Equipment` represents physical tools or items required to deliver an
        appointment — facials require a steam machine, massages require a
        table, etc. Each appointment type can declare equipment it needs;
        availability calculations then only offer slots where the required
        equipment is free.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for this piece of equipment.
          example: 5f1234567890abcdef123456
        name:
          type: string
          description: Display name shown to staff in the admin UI. Plain text only.
          example: Steam Machine A
        description:
          type: string
          nullable: true
          description: Optional internal note about this equipment — e.g. model number, service schedule, location.
          example: Lucas Champion steam unit serviced annually.
        quantity:
          type: number
          description: |
            Number of units of this equipment the site has. Used by
            availability calculations to enforce concurrency limits (an
            appointment requiring 1 unit can only run when at least one
            unit is free).
          example: 2
        site_id:
          type: string
          format: uuid
          description: ID of the site this equipment belongs to.
          example: 11111111-1111-1111-1111-111111111111
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation that owns this equipment. Defaults to the caller's primary organisation on create.
          example: 22222222-2222-2222-2222-222222222222
      required:
        - id
        - name
        - quantity
        - site_id
        - organisation_id
    DiscountType:
      title: DiscountType
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the discount type.
        applicable_for:
          type: string
          description: Where the discount type is able to be applied.
          example: app_and_booking_engine
          enum:
            - app_only
            - app_and_booking_engine
        code:
          type: string
          description: |
            The code for the discount type.
            When the type is a promo code, this will be what the customer enters in on the booking engine to receive their discount, e.g. `SUMMER23`.
            Or, if the discount type is for app use, this is what is used for reporting.
          example: SUMMER23
        description:
          type: string
          description: |
            This provides further details on what the discount type can be used for.
            It's up to the user to provide this.
          example: For 15% off any order placed from Jun-Aug 2023
          nullable: true
        amount_type:
          type: string
          description: |
            The type of discount. For a promo code, this will always be a percentage.
          example: percentage
          enum:
            - monetary
            - percentage
        discount_amount:
          type: integer
          description: |
            The value of the discount to be applied when a discount type is used.
            This can be used as a monetary amount or percentage for an in-app discount type and is set to percentage for a promo code.
          example: 15
          nullable: true
        currency:
          type: string
          description: |
            The currency of the monetary discount to be applied if `amount_type` is set to `monetary` for an in-app discount type.
            This is associated with the site.
          example: gbp
        is_custom_amount:
          type: boolean
          default: false
          example: false
          description: |
            Whether the amount provided is customisable.
            This can only be toggled for in-app discount types.
        valid_from:
          type: string
          format: date
          description: |
            The start date which the promo code is valid from, based on the date the order is submitted.
            This field is null if `applicable_for` is set to `app_only`.
            For a promo code to be valid for use on an order, this must be set.
          example: '2023-06-01'
          nullable: true
        valid_to:
          type: string
          format: date
          description: |
            The end date which the promo code is valid until, based on the date the order is submitted.
            This field is null if `applicable_for` is set to `app_only`.
            This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
          example: '2023-09-01'
          nullable: true
        item_date_from:
          type: string
          format: date
          description: |
            The start date for when the purchased item occurs, based on the date the item is booked for.
            This field is null if `applicable_for` is set to `app_only`.
            This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
          example: '2023-09-01'
          nullable: true
        item_date_to:
          type: string
          format: date
          description: |
            The end date for when the purchased item occurs, based on the date the item is booked for.
            This field is null if `applicable_for` is set to `app_only`.
            This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
          example: '2023-09-30'
          nullable: true
        item_date_weekdays:
          type: array
          description: |
            The days the purchased item takes place on.
            For example, the promo code could be valid for massages which only occur on Mondays.
            By default, this array contains all enum values and the occurrence of the purchased items is not restricted to any days.
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
        item_time_from:
          type: string
          description: |
            The start time for when the purchased item takes place.
            For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
            This field is null if `applicable_for` is set to `app_only`.
            This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
          example: '10:00'
          nullable: true
        item_time_to:
          type: string
          description: |
            The end time for when the purchased item takes place.
            For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
            This field is null if `applicable_for` is set to `app_only`.
            This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
          example: '14:00'
          nullable: true
        valid_offerings:
          type: array
          description: |
            An array of offerings which the promo code is valid for.
            By default, this array is empty and the discount will not be applied to any items in the order.
            If this array includes offerings, the discount will be applied to only those selected items in the order.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        max_uses:
          type: integer
          description: |
            The maximum number of times the code can be used in total.
            By default, this value is null which means that this number is unlimited.
          example: 100000
          nullable: true
        has_been_redeemed:
          type: boolean
          default: false
          example: false
          description: |
            Whether the promo code has been used by at least one customer.
            If this value is true, the `code` field is no longer editable.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the discount type is associated with.
        created_at:
          type: string
          format: date-time
          description: The date and time the discount type was created.
          example: '2023-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time the discount type was updated.
          example: '2023-01-01T00:00:00Z'
        deleted_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the discount type was deleted.
          example: '2023-01-01T00:00:00Z'
      required:
        - id
        - applicable_for
        - code
        - description
        - amount_type
        - discount_amount
        - currency
        - is_custom_amount
        - valid_from
        - valid_to
        - item_date_from
        - item_date_to
        - item_date_weekdays
        - item_time_from
        - item_time_to
        - valid_offerings
        - max_uses
        - has_been_redeemed
        - site_id
        - created_at
        - updated_at
        - deleted_at
    OfferingIdentifierRequest:
      title: OfferingIdentifierRequest
      type: object
      additionalProperties: false
      properties:
        offering_type:
          type: string
          description: The type of the offering.
          example: appointment
        offering_id:
          type: string
          format: mongo-id
          description: The ID of the offering.
      required:
        - offering_type
        - offering_id
    DiscountTypeSummary:
      title: DiscountTypeSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the discount type.
        applicable_for:
          type: string
          description: Where the discount type is able to be applied.
          example: app_and_booking_engine
          enum:
            - app_only
            - app_and_booking_engine
        code:
          type: string
          description: |
            The code for the discount type.
            When the type is a promo code, this will be what the customer enters in on the booking engine to receive their discount, e.g. `SUMMER23`.
            Or, if the discount type is for app use, this is what is used for reporting.
          example: SUMMER23
      required:
        - id
        - applicable_for
        - code
    ExternalIdType:
      title: ExternalIdType
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The Trybe ID of the external ID type.
        key:
          type: string
          description: The key of the external ID type.
          example: my_external_system
        name:
          type: string
          description: The name of the external ID type.
          example: My External System
        description:
          type: string
          nullable: true
          description: The description of the external ID type.
          example: ID of the basket in my external system
        applies_to:
          type: string
          description: The type of object the external ID type applies to.
          enum:
            - basket
        site_ids:
          type: array
          items:
            type: string
            format: uuid
            description: The ID of the site the external ID type is associated with.
        all_sites:
          type: boolean
          description: Whether the external ID type is associated with all sites.
        is_archived:
          type: boolean
          description: Whether the external ID type is archived.
      required:
        - id
        - key
        - name
        - description
        - applies_to
        - site_ids
        - all_sites
        - is_archived
    HotelRoomType:
      title: HotelRoomType
      description: A bookable category of overnight accommodation (e.g. "Deluxe Double", "Family Suite"). The room type defines pricing rates, occupancy limits and inventory pool that overnight bookings draw from; individual rooms in the property are assigned at check-in time, not at booking time.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the hotel room type.
        name:
          type: string
          description: The name of the hotel room type.
          example: Deluxe Double
        description:
          type: string
          nullable: true
          description: A description of the hotel room type.
          example: Enjoy a relaxing night in our deluxe room.
        external_id:
          type: string
          description: An ID of this room type from the external system.
          example: DDBL
        external_source:
          type: string
          description: The external source of this room type.
          example: pms_name
        images:
          type: array
          description: An array of images of this hotel room type.
          items:
            $ref: '#/components/schemas/Media'
        image:
          type: string
          description: The main image for this hotel room type.
          $ref: '#/components/schemas/Media'
        updated_at:
          type: string
          format: date-time
          description: The time when this hotel room type was last updated.
        site_id:
          type: string
          format: uuid
          description: The ID of the site this hotel room type belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this hotel room type belongs to.
      required:
        - id
        - name
        - description
        - external_id
        - external_source
        - updated_at
        - site_id
        - organisation_id
    SuggestedCombination:
      type: object
      title: SuggestedCombination
      additionalProperties: false
      properties:
        room_id:
          type: string
          format: mongo-id
          description: The ID of the suggested room.
        practitioner_ids:
          type: array
          description: The IDs of the suggested practitioners.
          items:
            type: string
            format: mongo-id
      required:
        - room_id
        - practitioner_ids
    AppointmentSlot:
      type: object
      title: AppointmentSlot
      additionalProperties: false
      properties:
        start_time:
          type: string
          format: date-time
          description: The start time for the appointment.
        end_time:
          type: string
          format: date-time
          description: The end time for the appointment.
        duration:
          type: string
          description: The duration of the appointment in minutes
          example: 60
        end_buffer:
          type: string
          description: The number of minutes of buffer (cleaning time) included in the end time.
          example: 15
        practitioner_ids:
          type: array
          description: The IDs of the practitioners who are available to offer this appointment.
          items:
            type: string
            format: mongo-id
        room_ids:
          type: array
          description: The IDs of the practitioners who are available to offer this appointment. (Internal users only)
          items:
            type: string
            format: mongo-id
        equipment_ids:
          type: array
          description: The IDs of the equipment which may be used to offer this appointment. (Internal users only)
          items:
            type: string
            format: mongo-id
        suggested_combinations:
          type: array
          description: An array of suggested combinations, in order of preference.
          items:
            $ref: '#/components/schemas/SuggestedCombination'
        total_quantity:
          type: integer
          description: The total number of slots that could be offered at this time if all resources were available.
          example: 5
        quantity_available:
          type: integer
          description: The number of slots currently available.
          example: 3
        is_valid:
          type: boolean
          description: Whether the slot is allowed at this time.
        price:
          type: string
          description: The price of the slot, in the smallest denomination.
          example: 8995
        currency:
          type: string
          description: The currency code of the price
          example: gbp
        nonoptimal_practitioner_allocation:
          type: boolean
          description: |
            Whether this slot is considered 'non-optimal' for some practitioners, i.e. it would leave
            an amount of white space on the calendar that is difficult to fill.
        nonoptimal_practitioner_ids:
          type: array
          description: An array of IDs for practitioners for whom this slot would be 'non-optimal'.
          items:
            type: string
        no_availability_reason:
          type: string
          description: A reason code for the slot having no availability, if applicable.
          enum:
            - time_passed
            - date_passed
            - no_longer_bookable
            - not_yet_bookable
            - partner_slot_not_available
            - partner_offering_not_allowed
            - start_time_not_allowed
            - no_equipment_available
            - no_rooms_available
            - no_practitioners_available
            - invalid_offering_settings
            - not_offered_on_date
        no_availability_message:
          type: string
          description: A user-friendly reason for the slot having no availability, if applicable.
          example: No practitioners are available.
        bookable_from:
          type: string
          format: date-time
          nullable: true
          description: The earliest date and time that this slot may be booked, if applicable.
        bookable_to:
          type: string
          format: date-time
          nullable: true
          description: The date and time after which this slot may not be booked, if applicable.
      required:
        - start_time
        - end_time
        - duration
        - end_buffer
        - practitioner_ids
        - total_quantity
        - quantity_available
        - price
        - currency
        - bookable_from
        - bookable_to
    AppointmentEnquiryAvailabilityResult:
      type: object
      title: AppointmentEnquiryAvailabilityResult
      additionalProperties: false
      properties:
        can_enquire:
          type: boolean
          description: Whether the enquiry can be accepted for the given times.
        cannot_enquire_reason:
          type: string
          description: A reason code for why the enquiry cannot be accepted, if applicable.
          enum:
            - no_slots_found
            - time_passed
            - bookable_slots_found
            - no_slots_for_num_guests
        cannot_enquire_message:
          type: string
          description: A user-friendly message for why the enquiry cannot be accepted, if applicable.
          example: The appointment already has availability to book at this time.
        bookable_slots:
          type: array
          items:
            $ref: '#/components/schemas/AppointmentSlot'
      required:
        - can_enquire
    TableReservationOption:
      title: TableReservationOption
      type: object
      description: An option that modifies the table reservation in some way.
      additionalProperties: false
      properties:
        id:
          type: string
          description: An ID for the option.
          example: '1234'
        name:
          type: string
          description: A name for the option.
          example: Afternoon Tea promotion
        optional:
          type: boolean
          description: Whether this option is optional.
        provider_id:
          type: string
        type:
          type: string
          nullable: true
          description: A string identifying the type of the option, if applicable.
          example: promotion
      required:
        - id
        - name
        - optional
        - provider_id
        - type
    TableReservationSlot:
      title: TableReservationSlot
      type: object
      additionalProperties: false
      properties:
        start_time:
          type: string
          format: date-time
          description: The start date and time of the slot.
          example: '2024-04-01T12:00:00+01:00'
        end_time:
          type: string
          format: date-time
          description: The start date and time of the slot.
          example: '2024-04-01T13:00:00+01:00'
        duration:
          type: integer
          description: The duration of the slot in minutes.
          example: 60
        is_fixed_end_time:
          type: boolean
          description: Whether the end time is fixed or open-ended.
        price:
          type: integer
          description: The price of the slot, if applicable.
        is_available:
          type: boolean
          description: Whether the slot is available.
        requires_credit_card:
          type: boolean
          description: This slot requires a credit card guarantee.
        options:
          type: array
          items:
            $ref: '#/components/schemas/TableReservationOption'
      required:
        - start_time
        - end_time
        - duration
        - is_fixed_end_time
        - price
        - is_available
        - options
        - requires_credit_card
    IntakeFormQuestion:
      type: object
      title: IntakeFormQuestion
      additionalProperties: false
      properties:
        id:
          description: Unique identifier for the intake form question.
          type: string
          format: object-id
        additional_details:
          description: Whether additional details are enabled.
          type: boolean
          nullable: true
        exact_number:
          description: Exact number constraint for the question.
          type: string
          nullable: true
        multiple_choice_answers:
          description: Available answers for multiple choice questions.
          type: array
          nullable: true
          items:
            type: object
            title: IntakeFormQuestionMultipleChoiceAnswer
            additionalProperties: false
            properties:
              id:
                description: The answer identifier.
                type: string
              text:
                description: The answer text.
                type: string
            required:
              - id
              - text
        multiple_select_option:
          description: Option for multiple select behavior.
          type: string
          nullable: true
        multiple_selection:
          description: Whether multiple answers can be selected.
          type: boolean
          nullable: true
        order:
          description: Display order of the question within its section.
          type: integer
          nullable: true
        placeholder:
          description: Placeholder text for the input field.
          type: string
          nullable: true
        question:
          description: The question text.
          type: string
        range:
          description: A two-element array representing a min/max range.
          type: array
          nullable: true
          items:
            type: integer
            nullable: true
          minItems: 2
          maxItems: 2
        required:
          description: Whether the question must be answered.
          type: boolean
          nullable: true
        terms_statement:
          description: The terms statement text for terms_conditions type questions.
          type: string
          nullable: true
        type:
          description: The type of question.
          type: string
          enum:
            - additional_details
            - date_time
            - email
            - multiple_choice
            - phone
            - terms_conditions
            - text_long
            - text
            - yes_no
      required:
        - id
        - additional_details
        - exact_number
        - multiple_choice_answers
        - multiple_select_option
        - multiple_selection
        - order
        - placeholder
        - question
        - range
        - required
        - terms_statement
        - type
    IntakeFormSection:
      title: IntakeFormSection
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        created_at:
          type: string
          format: date-time
          nullable: true
        deleted_at:
          type: string
          format: date-time
          nullable: true
        description:
          type: string
          description: |
            Admin-facing description of what this intake form section captures.
            Visible in the questionnaire builder but not shown to customers.
          example: Pre-treatment health questions and consent
        intro_text:
          type: string
          nullable: true
          description: |
            Optional rich-text shown to the customer at the top of the section,
            before the questions. Markdown is rendered.
          example: |
            Please answer honestly — these questions help us tailor your
            treatment safely.
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        outro_text:
          type: string
          nullable: true
          description: |
            Optional rich-text shown to the customer at the foot of the section,
            after the questions. Useful for thank-yous or follow-up instructions.
          example: |
            Thank you. Please proceed to checkout when you're ready.
        questions:
          type: array
          items:
            $ref: '#/components/schemas/IntakeFormQuestion'
        title:
          type: string
          description: |
            Customer-facing heading for the section. Plain text only — HTML
            tags are stripped.
          example: Health Declaration
        type:
          type: string
          nullable: true
          enum:
            - mandatory
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - created_at
        - description
        - intro_text
        - offerings
        - outro_text
        - questions
        - title
        - type
        - updated_at
    OrderableIntakeFormSection:
      title: OrderableIntakeFormSection
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        title:
          type: string
      required:
        - id
        - title
    201-content-application~1json-schema:
      title: CreateIntakeFormSectionResponse
      type: object
      additionalProperties: false
      properties:
        data:
          $ref: '#/components/schemas/IntakeFormSection'
      required:
        - data
    IntakeFormQuestionWritableFields:
      title: IntakeFormQuestionWritableFields
      description: |
        Shared schema for writable fields on `IntakeFormQuestion` — used as
        the `allOf` base for create and update request bodies. The
        `required` validation differs per operation and is layered on top
        of this base.
      type: object
      additionalProperties: false
      properties:
        question:
          type: string
          description: The question text.
          maxLength: 255
          example: Do you have any allergies?
        type:
          type: string
          description: |
            The type of question. Drives input rendering on the customer
            intake form and unlocks the type-specific fields below.
          enum:
            - additional_details
            - date_time
            - email
            - multiple_choice
            - phone
            - terms_conditions
            - text_long
            - text
            - yes_no
        multiple_choice_answers:
          type: array
          nullable: true
          description: |
            Available answers when `type=multiple_choice`. Must contain at
            least two entries when the type is `multiple_choice`.
          items:
            type: object
            title: IntakeFormQuestionMultipleChoiceAnswerInput
            additionalProperties: false
            properties:
              id:
                type: integer
                description: |
                  Stable integer key for the answer. Used to reference the
                  answer in `range` constraints and from the customer's
                  submitted response.
              text:
                type: string
                maxLength: 255
                description: Display label for the answer.
            required:
              - id
              - text
        multiple_select_option:
          type: string
          nullable: true
          description: |
            Optional bonus label rendered alongside the multiple-choice
            answers (e.g. "Other"). Only meaningful when
            `type=multiple_choice`.
        multiple_selection:
          type: boolean
          nullable: true
          description: |
            Whether the customer can pick more than one
            `multiple_choice_answers` entry. Only meaningful when
            `type=multiple_choice`.
        additional_details:
          type: boolean
          nullable: true
          description: |
            When true, the customer is prompted for free-text "additional
            details" alongside the structured answer.
        exact_number:
          type: string
          nullable: true
          description: |
            Optional exact-number constraint for numeric questions.
        range:
          type: array
          nullable: true
          description: |
            A two-element `[min, max]` constraint on
            `multiple_choice_answers` selections. Both bounds are inclusive;
            omit either to leave it unbounded.
          minItems: 2
          maxItems: 2
          items:
            type: integer
            nullable: true
        terms_statement:
          type: string
          nullable: true
          description: |
            Terms text rendered alongside `type=terms_conditions`
            questions. HTML is sanitised to the site's allowed-tag list.
        placeholder:
          type: string
          nullable: true
          description: Placeholder text for the input field.
        required:
          type: boolean
          nullable: true
          description: Whether the customer must answer this question.
    Offering:
      title: OfferingSearchOffering
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        categories:
          type: array
          items:
            title: OfferingSearchOfferingCategory
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
              name:
                type: string
            required:
              - id
              - name
        image_url:
          type: string
          nullable: true
        inventory_categories:
          type: array
          items:
            title: OfferingSearchOfferingInventoryCategory
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
              name:
                type: string
            required:
              - id
              - name
        members_only:
          type: boolean
        name:
          type: string
        offering_type:
          $ref: '#/components/schemas/OfferingType'
      required:
        - id
        - categories
        - image_url
        - members_only
        - name
        - offering_type
    schemas_Category-2:
      type: object
      title: Category
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the category.
        name:
          type: string
          description: The name of the category.
          example: Massages
      required:
        - id
        - name
    PackageOfferingEmailOptions:
      title: PackageOfferingEmailOptions
      type: object
      additionalProperties: false
      required:
        - hide_prices
      properties:
        hide_prices:
          type: boolean
          description: Enable to hide prices from customer emails, in cases where the customer didn't purchase the item directly.
          example: true
    PackagePriceRule:
      title: PackagePriceRule
      type: object
      additionalProperties: false
      required:
        - id
        - package_id
        - date_from
        - date_to
        - time_from
        - time_to
        - weekdays
        - price
      properties:
        id:
          type: string
          description: The ID of the price rule.
          example: 5dcb47800000000000000010
        package_id:
          type: string
          description: The ID of the package the price rule relates to.
          example: 5dcb47800000000000000010
        date_from:
          type: string
          format: date
          nullable: true
          description: The rule should apply to packages starting on or after this date.
          example: '2020-02-01'
        date_to:
          type: string
          format: date
          nullable: true
          description: The rule should not apply to packages starting after this date.
          example: '2020-04-01'
        time_from:
          type: string
          nullable: true
          description: The rule will apply to packages that have bookings starting on or after this time.
          example: '10:00'
        time_to:
          type: string
          nullable: true
          description: The rule will apply to packages that have bookings starting before this time.
          example: '14:00'
        weekdays:
          type: array
          description: The rule should apply to packages starting on any of these weekdays.
          items:
            type: string
            example: monday
        price:
          type: integer
          description: The price of the package.
          example: 20000
    schemas_Package:
      title: Package
      description: A bundled set of offerings sold as a single product (e.g. a "Spa Day" combining treatments, lunch and pool access). Packages declare their allocations — which offering types they include and in what quantities — and how the inner items are scheduled, priced and discounted at checkout.
      type: object
      additionalProperties: false
      required:
        - id
        - allocations
        - categories
        - category_ids
        - cross_sell_offerings
        - currency
        - customer_cancellation_min_duration
        - customer_cancellation_permitted
        - customer_reschedule_min_duration
        - customer_reschedule_permitted
        - customers_only
        - default_revenue_centre
        - description
        - email_options
        - external_id
        - include_pricing_on_calendar
        - item_choices
        - max_advance_bookings_interval
        - max_daily_duration
        - max_guests
        - max_per_basket
        - max_per_guest
        - members_only
        - membership_booking_windows
        - membership_booking_windows_enabled
        - meta
        - min_advance_bookings_interval
        - min_guests
        - name
        - offered_online
        - overnight_package_config
        - prevent_choice_overlaps
        - price_rules
        - private
        - product_code
        - related_retail_offerings
        - separate_couples_package_choices
        - site_id
        - standard_price
        - upsell_offerings
        - deleted_at
        - updated_at
      properties:
        id:
          type: string
          description: The ID of the package.
          example: 5dcb47800000000000000010
        allocations:
          type: object
          additionalProperties:
            type: integer
        categories:
          description: The category associated with this package type
          type: array
          items:
            $ref: '#/components/schemas/schemas_Category-2'
        category_ids:
          description: The category IDs associated with this package type
          type: array
          items:
            type: string
        cross_sell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        currency:
          type: string
          description: The ISO-4217 currency code in lower case
          example: gbp
        customer_cancellation_min_duration:
          type: string
          nullable: true
          description: The minimum duration that must be left before the booking in order for the customer to cancel, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
        customer_cancellation_permitted:
          description: Whether bookings of this type may be cancelled online by customers. A value of `unpaid` means this booking my be cancelled only if no payments have been recorded against the order it is part of.
          $ref: '#/components/schemas/customerCancellationPermitted'
        customer_reschedule_min_duration:
          type: string
          nullable: true
          description: The minimum duration that must be left before the booking in order for the customer to reschedule, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
        customer_reschedule_permitted:
          description: Whether bookings of this type may be rescheduled online by customers. A value of `unpaid` means this booking may be rescheduled only if no payments have been recorded against the order it is part of.
          $ref: '#/components/schemas/customerReschedulePermitted'
          nullable: true
        customers_only:
          type: boolean
          example: false
        default_revenue_centre:
          type: string
          nullable: true
          description: The default revenue centre to fall back to to balance allocations
        description:
          type: string
          description: A description of the package
          example: Buy together and save
        email_options:
          $ref: '#/components/schemas/PackageOfferingEmailOptions'
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        image:
          $ref: '#/components/schemas/Media'
        include_pricing_on_calendar:
          type: boolean
          description: Whether the booking engine calendar should display pricing under each date
        item_choices:
          type: array
          description: An array of choices for items which may be included in this package.
          items:
            type: object
            description: Details of a single choice for the current item.
            $ref: '#/components/schemas/PackageItemChoice'
        max_advance_bookings_interval:
          type: string
          nullable: true
          description: The maximum time before the package's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2W
        max_daily_duration:
          type: integer
          nullable: true
          description: The maximum amount of time between the start of the first and end of the last item on each day of a package, in minutes.
          example: 240
        max_guests:
          type: integer
          description: The maximum guests this package is for
          example: 2
        max_per_basket:
          type: integer
          nullable: true
          description: The maximum number of bookings that may be made in a single basket for this package.
          example: 1
        max_per_guest:
          type: integer
          nullable: true
          description: The maximum number of bookings that may be made by a single guest for this package.
          example: 1
        members_only:
          type: boolean
          description: Whether this package requires an active membership in order to book.
          example: true
        membership_booking_windows:
          type: array
          items:
            $ref: '#/components/schemas/MembershipBookingWindow'
        membership_booking_windows_enabled:
          type: boolean
          description: Whether membership-specific booking windows should be enabled for this package.
          example: true
        meta:
          title: PackageMeta
          type: object
          additionalProperties: false
          required:
            - title
            - description
          properties:
            description:
              type: string
              nullable: true
              description: The meta description of this offering. If not specified, it falls back to the description of the offering.
            title:
              type: string
              nullable: true
              description: The meta title of this offering. If not specified, it falls back to the name of the offering.
        min_advance_bookings_interval:
          type: string
          nullable: true
          description: The minimum time before the package's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2D
        min_guests:
          type: integer
          description: The minimum guests this package is for
          example: 2
        name:
          type: string
          description: The name of this package
          example: Treatment and Yoga
        offered_online:
          type: boolean
          description: Whether this session type is bookable online
        overnight_package_config:
          title: PackageOvernightPackageConfig
          type: object
          additionalProperties: false
          properties:
            enabled:
              type: boolean
              description: Whether this package is an overnight package.
              example: true
            rate_id:
              type: string
              description: The ID of the rate this package is associated with.
              example: 5dcb47800000000000000010
            num_nights:
              type: integer
              description: The number of nights this package is associated with.
              example: 1
        permitted_membership_type_ids:
          type: array
          description: |
            If this package is for members only, this property may be used to restrict the offering further
            so it may only be purchased by active members with of one of the given membership types.
          items:
            type: string
        prevent_choice_overlaps:
          type: boolean
          description: Whether to prevent booking choices in this package from overlapping times.
          example: true
        price_rules:
          type: array
          description: The rules defining prices for this package
          items:
            $ref: '#/components/schemas/PackagePriceRule'
        private:
          type: boolean
          description: Whether this is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
        product_code:
          type: string
          nullable: true
          description: A custom product code for the package.
          example: MAS123
        related_retail_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        separate_couples_package_choices:
          type: boolean
          description: If this is a couples package, defines whether each person should be able to make different choices.
        site_id:
          type: string
          description: The ID of the site the package belongs to.
          example: 00000000-0000-0000-0000-111111111111
        standard_price:
          type: integer
          nullable: true
          description: The standard price for this package, in the smallest currency unit (e.g. pence). `null` if a standard price hasn't been configured — this is distinct from a price of zero.
          example: 5000
        upsell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        visibility:
          $ref: '#/components/schemas/visibility'
        deleted_at:
          $ref: '#/components/schemas/deletedAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
    OfferingBasicLocaleStrings:
      title: OfferingBasicLocaleStrings
      description: Localised strings for an offering type in a non-English locale, covering name and description.
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
      required:
        - name
        - description
    ProductPriceRule:
      type: object
      title: ProductPriceRule
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the price rule.
          format: object-id
        product_id:
          type: string
          description: The ID of the product the price rule relates to.
          format: object-id
        date_from:
          type: string
          format: date
          description: The rule should apply to products sold on or after this date.
          example: '2020-02-01'
          nullable: true
        date_to:
          type: string
          format: date
          description: The rule should not apply to products sold after this date.
          example: '2020-04-01'
          nullable: true
        price:
          type: integer
          description: The price of the product as an integer of the smallest unit, ie pence.
          example: 20000
      required:
        - id
        - product_id
        - date_from
        - date_to
        - price
    schemas_Product:
      type: object
      title: Product
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the product
          format: mongo-id
        name:
          type: string
          description: The name of this product
          example: Dan's Hand Moisturiser
        currency:
          type: string
          description: The ISO-4217 currency code in lower case
          example: gbp
        description:
          type: string
          description: A description of the product
          example: For silky soft hands
          nullable: true
        external_id:
          type: string
          nullable: true
          description: An external identifier for the product.
        product_code:
          type: string
          description: A custom product code for the product.
          example: MAS123
          nullable: true
        price_from:
          type: integer
          description: The lowest price for the product as an integer of the smallest unit eg pence.
          example: 1000
          nullable: true
        price_to:
          type: integer
          description: The highest price for the product as an integer of the smallest unit eg pence.
          example: 5000
          nullable: true
        standard_price:
          type: integer
          description: The standard price for the product as an integer of the smallest unit eg pence. `null` if a standard price hasn't been configured — this is distinct from a price of zero.
          example: 5000
          nullable: true
        barcode:
          type: string
          description: The barcode of the product
          example: 5013635312160
          nullable: true
        inventory_product_id:
          type: string
          description: |
            The ID of the inventory product if this product is associated to one.
          format: object-id
          nullable: true
        image:
          $ref: '#/components/schemas/Media'
        offered_online:
          type: boolean
          description: Whether this product is available online
        private:
          type: boolean
          description: Whether this product is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
        site_id:
          type: string
          description: The ID of the site this product belongs to
          format: uuid
        tag_ids:
          type: array
          items:
            type: string
          deprecated: true
        tags:
          type: array
          deprecated: true
          items:
            type: object
            additionalProperties: false
            title: ProductTag
            properties:
              id:
                type: string
                format: object-id
                description: The ID of the tag
              name:
                type: string
                description: The name of the tag
                example: Moisturisers
              organisation_id:
                type: string
                description: The organisation ID which this tag belongs to
                format: uuid
            required:
              - id
              - name
              - organisation_id
        category_ids:
          type: array
          description: An array of category IDs that this product belongs to
          items:
            type: string
            format: uuid
        categories:
          type: array
          description: An array of categories that this product belongs to
          items:
            type: object
            additionalProperties: false
            title: ProductCategory
            properties:
              id:
                type: string
                format: object-id
                description: The ID of the category
              name:
                type: string
                description: The name of the category
                example: Moisturisers
            required:
              - id
              - name
        price_rules:
          type: array
          description: The rules defining prices for this product
          items:
            $ref: '#/components/schemas/ProductPriceRule'
        revenue_centre:
          type: string
          description: The revenue centre to assign revenue to for this product
          example: spa
        customer_cancellation_permitted:
          description: Whether this product may be cancelled online by customers. A value of `unpaid` means this product may be cancelled only if no payments have been recorded against the order it is part of.
          $ref: '#/components/schemas/customerCancellationPermitted'
        customer_cancellation_min_duration:
          type: string
          description: The minimum duration that must be left before the booking this product is a part of in order for the customer to cancel, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
        updated_at:
          type: string
          format: date-time
          description: The time and date that the product was last updated.
        deleted_at:
          type: string
          format: date-time
          description: The time and date that the product was archived.
          nullable: true
        brand_id:
          type: string
          format: uuid
          description: The brand ID of the product.
          nullable: true
      required:
        - id
        - name
        - currency
        - description
        - external_id
        - product_code
        - price_from
        - price_to
        - standard_price
        - barcode
        - inventory_product_id
        - image
        - offered_online
        - private
        - site_id
        - tag_ids
        - tags
        - category_ids
        - categories
        - price_rules
        - revenue_centre
        - updated_at
        - deleted_at
    CreateProduct:
      title: CreateProduct
      type: object
      additionalProperties: false
      required:
        - name
      properties:
        name:
          type: string
          description: |
            Display name of the retail product, shown on the storefront,
            in the POS product picker, on receipts, and on reports. Plain
            text; must not contain HTML. 1-255 characters.
          example: Dan's Hand Moisturiser
        product_code:
          type: string
          nullable: true
          description: A custom product code for the product.
          example: MAS123
        external_id:
          type: string
          nullable: true
          description: An external identifier for the product.
          example: ext-prod-moisturiser
        currency:
          type: string
          description: The ISO-4217 currency code in lower case.
          example: gbp
        description:
          type: string
          nullable: true
          description: A description of the product.
          example: For silky soft hands
        standard_price:
          type: integer
          nullable: true
          description: The standard price for the product, in the smallest currency unit eg pence. Optional at create time — products can be created without a standard price and have one configured later.
          example: 5000
        offered_online:
          type: boolean
          description: Whether this product is available online.
          example: true
        barcode:
          type: string
          nullable: true
          description: The barcode of the product. Must be unique within the site.
          example: '5013635312160'
        private:
          type: boolean
          description: Whether this product is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
          example: false
        visibility:
          type: string
          description: The visibility status of the product.
          enum:
            - public
            - link_only
            - private
          example: public
        inventory_product_id:
          type: string
          nullable: true
          format: object-id
          description: |
            Optional identifier of the inventory product that backs this
            retail product. When linked, sales of this product decrement
            stock on the inventory product. Pass `null` for products that
            do not draw down stock.
        image_id:
          type: string
          nullable: true
          description: |
            Media ID of the primary product image, shown on the storefront
            product page and in the POS picker. Upload via
            [`createMedia`](/endpoints/Media#createMedia) first and pass
            the returned ID here.
          example: 5f1234567890abcdef123456
        revenue_centre:
          type: string
          nullable: true
          description: The revenue centre to assign revenue to for this product.
          example: spa_retail
        category_ids:
          type: array
          nullable: true
          description: An array of category IDs the product belongs to
          items:
            type: string
            format: uuid
        brand_id:
          type: string
          format: uuid
          nullable: true
          description: The brand ID of the product
    UpdateProduct:
      title: UpdateProduct
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          description: |
            Display name of the retail product, shown on the storefront,
            in the POS product picker, on receipts, and on reports. Plain
            text; must not contain HTML. 1-255 characters.
          example: Sample Product
        product_code:
          type: string
          nullable: true
          description: Site-unique SKU used to identify this product at the till and on receipts. Free-text and not validated against any pattern; choose a stable identifier that maps cleanly to your accounting or stock system. Pass `null` to clear an existing code.
          example: PROD-12345
        currency:
          type: string
          description: The currency of the product price, as a 3-letter ISO currency code
          example: GBP
        description:
          type: string
          nullable: true
          description: A brief description of the product
          example: This is a sample product description.
        standard_price:
          type: integer
          nullable: true
          description: The standard price for the product, in the smallest currency unit eg pence. Pass `null` to clear a previously-set standard price.
          example: 5000
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
          example: ext-prod-moisturiser
        offered_online:
          type: boolean
          description: Whether this product is offered for sale online
          example: true
        barcode:
          type: string
          nullable: true
          description: The barcode of the product
          example: 123456789
        private:
          type: boolean
          description: Whether this product is private
          example: false
        visibility:
          type: string
          description: The visibility status of the product
          enum:
            - public
            - link_only
            - private
          example: public
        inventory_product_id:
          type: string
          nullable: true
          description: ID of the linked stock-tracked inventory product. When set, each sale of this retail product decrements the inventory item's stock count; pass `null` to break the link and stop tracking inventory for this product.
          example: INV-12345
        image_id:
          type: string
          nullable: true
          description: The image ID of the product
          example: '123'
        revenue_centre:
          type: string
          nullable: true
          description: The revenue centre of the product
          example: spa_retail
        customer_cancellation_permitted:
          description: Whether this product may be cancelled online by customers. A value of `unpaid` means this product may be cancelled only if no payments have been recorded against the order it is part of
          $ref: '#/components/schemas/customerCancellationPermitted'
        customer_cancellation_min_duration:
          type: string
          description: The minimum duration that must be left before the booking this product is a part of in order for the customer to cancel, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
        category_ids:
          type: array
          description: An array of category IDs the product belongs to
          items:
            type: string
            format: uuid
        brand_id:
          type: string
          format: uuid
          description: The brand ID of the product
    Room:
      title: Room
      description: |
        A `Room` is a physical space in which appointments are delivered.
        Rooms have capacity (1 = single occupancy, >1 = multi-guest), an
        availability schedule, and optional tags / zones. They power room
        allocation when an appointment is booked: the availability engine
        picks an unoccupied room whose capacity, tags, and zones match the
        appointment type.
      type: object
      additionalProperties: false
      required:
        - id
        - organisation_id
        - site_id
        - name
        - capacity
        - availability_rules
        - suitable_for_tags
        - tag_ids
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier of the room.
          example: 5dcb47800000000000000000
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation the room belongs to.
          example: 0193b6e0-3b56-7000-9f50-9d3d5e2c1111
        site_id:
          type: string
          format: uuid
          description: ID of the site the room belongs to. A room is scoped to exactly one site.
          example: 0193b6e0-3b56-7000-9f50-9d3d5e2c2222
        name:
          type: string
          description: |
            Display name for the room. Visible to staff in the calendar and
            admin UI; not shown to customers.
          example: Treatment Room 1
        capacity:
          type: integer
          minimum: 1
          description: |
            How many concurrent bookings the room can host. `1` means
            single-occupancy (appointments exclusively block the room);
            values > 1 enable multi-guest sharing when the appointment
            type opts in via `allocate_multi_capacity_rooms`.
          example: 1
        availability_rules:
          type: array
          description: |
            Per-day availability windows that override the site's opening
            hours for this room. Empty array means the room follows site
            opening hours.
          items:
            $ref: '#/components/schemas/AvailabilityRule'
        suitable_for_tags:
          type: array
          description: |
            Tag IDs that this room is suitable for. The availability
            engine matches these against the booking's required tags to
            decide if the room can host the appointment (e.g. a "wet
            room" tag for hydrotherapy treatments).
          items:
            type: string
            format: object-id
        tag_ids:
          type: array
          description: |
            Free-form tag IDs attached to the room for reporting and
            filtering. Distinct from `suitable_for_tags` — these don't
            affect allocation logic.
          items:
            type: string
            format: object-id
        tags:
          type: array
          description: Hydrated `Tag` records for the room's `tag_ids`.
          items:
            $ref: '#/components/schemas/Tag'
        zones:
          type: array
          description: |
            Hydrated `Zone` records this room belongs to. Zones group
            rooms in the floor plan and are used for spatial constraints
            in availability.
          items:
            $ref: '#/components/schemas/Zone'
    SoldBy:
      title: OrderItemSoldBy
      type: object
      additionalProperties: false
      required:
        - id
        - name
        - type
      properties:
        id:
          type: string
        name:
          type: string
        type:
          type: string
          enum:
            - practitioner
            - user
            - ''
    OrderItemRevenueSummary:
      type: object
      title: OrderItemRevenueSummary
      additionalProperties: false
      properties:
        revenue_centre:
          description: The key of the revenue centre.
          type: string
          nullable: true
          example: spa
        fee_type:
          description: For membership sales, which part of the sale this line represents. Null for non-membership items.
          type: string
          nullable: true
          enum:
            - joining_fee
            - pro_rata
          example: joining_fee
        revenue_centre_name:
          description: A friendly name for the revenue centre.
          type: string
          nullable: true
          example: Spa
        amount:
          description: The amount allocated to this revenue centre, in minor units.
          type: integer
          example: 12000
        net_amount:
          description: The net amount allocated to this revenue centre, in minor units.
          type: integer
          example: 10000
      required:
        - revenue_centre
        - revenue_centre_name
        - amount
        - net_amount
    OrderItem:
      type: object
      title: OrderItem
      additionalProperties: false
      properties:
        id:
          description: The ID of the basket item.
          type: string
          format: object-id
        basket_id:
          description: The ID of the basket this item belongs to.
          type: string
          format: object-id
        order_ref:
          description: The order reference of the basket this item belongs to.
          type: string
          example: TRY03
        order_status:
          description: The status of the basket this item belongs to.
          type: string
          example: settled
        revenue_date:
          description: The revenue date of the basket this item belongs to.
          type: string
          format: date
          nullable: true
        item_date:
          description: The date of this item. If the item is a booking, this will be the earliest date it takes place.
          type: string
          format: date-time
          nullable: true
        created_at:
          description: The date and time this item was created.
          type: string
          format: date-time
          nullable: true
        quantity:
          description: The quantity of this item. This is 1 in the majority of cases.
          type: integer
          example: 1
        offering_id:
          description: The ID of the offering this item is for.
          type: string
          format: object-id
        offering_type:
          description: The type of offering this item is for.
          type: string
          example: appointment
        offering_name:
          description: The name of the offering this item is for.
          type: string
          example: 60 Minute Massage
        total_cost:
          description: The total cost of the item, in minor units. Null for package items.
          type: integer
          nullable: true
          example: 15000
        net_total:
          description: The net total of the item, in minor units. Null for package items.
          type: integer
          nullable: true
          example: 12000
        sold_by:
          description: The staff member responsible for selling this item.
          $ref: '#/components/schemas/SoldBy'
          nullable: true
        revenues:
          description: A breakdown of revenue allocations for this item.
          type: array
          items:
            $ref: '#/components/schemas/OrderItemRevenueSummary'
      required:
        - id
        - basket_id
        - order_ref
        - order_status
        - revenue_date
        - item_date
        - quantity
        - offering_id
        - offering_type
        - offering_name
    OrderItemTotals:
      type: object
      title: OrderItemTotals
      additionalProperties: false
      properties:
        total_items:
          description: The total number of items matching the given filters.
          type: integer
          example: 120
        total_unique_orders:
          description: The total number of unique orders matching the given filters.
          type: integer
          example: 45
        net_total:
          description: The sum of net totals for all items matching the given filters, in minor units.
          type: integer
          example: 1200000
      required:
        - total_items
        - total_unique_orders
        - net_total
    OrderItemsReportResponse:
      title: OrderItemsReportResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/OrderItemTotals'
      required:
        - data
        - meta
        - links
        - totals
    QueuedJob:
      title: QueuedJob
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the queued job.
        status:
          type: string
          description: The status of the queued job.
          enum:
            - pending
            - complete
            - failed
        output:
          type: object
          description: The output of the queued job.
          additionalProperties: true
        created_at:
          type: string
          format: date-time
          description: The date and time the queued job was created.
          example: '2023-11-07T00:00:00+00:00'
        updated_at:
          type: string
          format: date-time
          description: The date and time the queued job was last updated.
          example: '2023-11-07T01:00:00+00:00'
      required:
        - id
        - status
        - output
        - created_at
        - updated_at
    OrderRevenueCentreAmounts:
      type: object
      title: OrderRevenueCentreAmounts
      additionalProperties: false
      properties:
        gross_amount:
          type: integer
          description: The gross revenue amount allocated to this revenue centre, in minor units.
        net_amount:
          type: integer
          description: The net revenue amount allocated to this revenue centre, in minor units.
      required:
        - gross_amount
        - net_amount
    OrderRevenueReportItem:
      type: object
      title: OrderRevenueReportItem
      additionalProperties: false
      properties:
        fiscal_receipt_id:
          type: string
          nullable: true
          description: The fiscal receipt ID for the order, if it has been fiscalised.
        order_ref:
          type: string
          description: The order reference.
          example: TRY03
        revenue_date:
          type: string
          format: date
          nullable: true
          description: The revenue date of the order.
        settled_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the order was settled.
        status:
          type: string
          description: The status of the order.
          example: settled
        gross_amount:
          type: integer
          description: The gross revenue amount for the order, across all final revenue lines, in minor units.
        net_amount:
          type: integer
          description: The net revenue amount for the order, across all final revenue lines, in minor units.
        vat:
          type: integer
          description: The VAT amount for the order, calculated as the gross amount minus the net amount, in minor units.
        currency:
          type: string
          description: The ISO currency code for the order's amounts.
          example: GBP
        payment_methods:
          type: array
          description: The unique payment processors used to pay for the order.
          items:
            type: string
            example: adyen
        card_brands:
          type: array
          description: The unique card brands used to pay for the order.
          items:
            type: string
            example: visa
        revenue_centres:
          type: object
          description: |
            A breakdown of revenue for the order by revenue centre, keyed by revenue centre code.
            Only revenue centres with a final revenue line for this order are included.
          additionalProperties:
            $ref: '#/components/schemas/OrderRevenueCentreAmounts'
      required:
        - fiscal_receipt_id
        - order_ref
        - revenue_date
        - settled_at
        - status
        - gross_amount
        - net_amount
        - vat
        - currency
        - payment_methods
        - card_brands
        - revenue_centres
    RevenueCentreSummary:
      type: object
      title: RevenueCentreSummary
      additionalProperties: false
      properties:
        key:
          type: string
          description: The ID of the revenue centre.
        name:
          type: string
          description: The name of the revenue centre.
          example: Website
      required:
        - key
        - name
    OrderRevenuesReportMeta:
      type: object
      title: OrderRevenuesReportMeta
      additionalProperties: false
      properties:
        revenue_centres:
          type: array
          description: |
            The site's configured revenue centres combined with any revenue centres present in the
            results. Revenue centres that appear in the results but are no longer configured on the
            site have a `null` name.
          items:
            $ref: '#/components/schemas/RevenueCentreSummary'
      required:
        - revenue_centres
    OrderRevenuesReportResponse:
      type: object
      title: OrderRevenuesReportResponse
      additionalProperties: false
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/OrderRevenueReportItem'
        meta:
          $ref: '#/components/schemas/OrderRevenuesReportMeta'
      required:
        - data
        - meta
    IntegrationConfig:
      title: IntegrationConfig
      description: The details of the integration config. Properties vary depending on the integration.
      type: object
      additionalProperties: true
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the integration config.
        name:
          type: string
          description: The name of the integration.
          example: Main PMS integration
          nullable: true
        type:
          type: string
          description: The type (category) of integration config.
          example: payments
        provider:
          type: string
          description: A key for the provider of the integration.
          example: guestline_rezlynx
        provider_name:
          type: string
          description: The name of the provider of the integration.
          example: Guestline (Rezlynx)
        enabled:
          type: boolean
          description: Whether the integration config is enabled or not.
          example: false
      required:
        - id
        - type
        - provider
        - provider_name
        - name
        - enabled
    schemas_TableReservationOption:
      title: TableReservationOption
      type: object
      description: An option that modifies the table reservation in some way.
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: An ID for the option.
        provider_id:
          type: string
          description: The provider's ID for this option.
          example: '1234'
        name:
          type: string
          description: A name for the option.
          example: Afternoon Tea promotion
        type:
          type: string
          description: A string identifying the type of the option, if applicable.
          example: promotion
        optional:
          type: boolean
          description: Whether this option may be chosen when booking, or is automatically applied.
      required:
        - id
        - name
        - optional
    TableReservationType:
      title: TableReservationType
      description: A bookable category of table reservation (e.g. "Dinner", "Brunch", "Cabana"). The type owns the configurable options (party size, duration, deposit) that the storefront presents to a guest and which subsequent reservations inherit. Soft-deleted types can be restored via the `/restore` endpoint.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: |
            Stable identifier for the table reservation type. Used by
            the storefront to fetch options and availability, and by
            reservations to record which type a guest booked into. Safe
            to expose to end users.
          example: 5dcb47800000000000000010
        name:
          type: string
          description: |
            Guest-facing display name for the reservation type. Shown on
            the storefront alongside the type's description and image.
            Keep concise — typically 1-3 words such as `Main restaurant`
            or `Sunday brunch`.
          example: Main restaurant
        integration_config:
          $ref: '#/components/schemas/IntegrationConfig'
          nullable: true
        description:
          type: string
          nullable: true
          description: A description of the table reservation type.
          example: Enjoy a relaxing meal in our main restaurant.
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
          example: resdiary:12345
        product_code:
          type: string
          nullable: true
          description: A custom product code for the table reservation type.
          example: DIN
        image:
          $ref: '#/components/schemas/Media'
        revenue_centre:
          type: string
          nullable: true
          description: The revenue centre to assign revenue to for this offering
          example: restaurant
        options:
          type: array
          items:
            $ref: '#/components/schemas/schemas_TableReservationOption'
        customer_reschedule_permitted:
          description: Whether bookings of this type may be rescheduled online by customers. A value of `unpaid` means this booking may be rescheduled only if no payments have been recorded against the order it is part of.
          $ref: '#/components/schemas/customerReschedulePermitted'
        customer_reschedule_min_duration:
          type: string
          nullable: true
          description: The minimum duration that must be left before the booking in order for the customer to reschedule, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
      required:
        - id
        - name
        - integration_config
        - description
        - external_id
        - product_code
        - revenue_centre
        - options
        - customer_reschedule_permitted
        - customer_reschedule_min_duration
    UpdateTableReservationOptionRequest-content-application~1json-schema:
      title: UpdateTableReservationOptionRequest
      type: object
      additionalProperties: false
      properties:
        provider_id:
          type: string
          description: The ID of this option with the provider of the table reservation, if applicable.
          example: '1234'
        name:
          type: string
          description: Customer-facing label for this option, shown alongside the reservation type during checkout. Plain text; appears verbatim in confirmation emails and on the POS so keep it concise and unambiguous.
          example: Afternoon tea
        type:
          type: string
          description: An identifier for the type of the option.
          example: promotion
        optional:
          type: boolean
          description: Whether this option may be selected or is included by default.
      required:
        - name
    CreateMedia:
      type: object
      title: CreateMedia
      additionalProperties: false
      properties:
        file:
          type: string
          format: binary
          description: The binary of the uploaded asset.
        image:
          type: string
          format: binary
          description: The binary of the uploaded asset.
        organisation_id:
          type: string
          format: uuid
          description: |
            Identifier of the organisation to upload this media item
            against. Media is scoped per organisation so each customer's
            library is isolated. The caller's API key must have access
            to this organisation.
        collection:
          type: string
          description: The collection which this media should be categorised under.
          enum:
            - library
    PayableSummary:
      title: PayableSummary
      type: object
      description: A summary of the model that the ledger line or posting relates to, usually a basket.
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the payable model.
          format: object-id
        type:
          type: string
          description: The type of the payable model.
          enum:
            - basket
            - customer
            - membership
            - import
        reference:
          type: string
          description: A reference for the payable model.
          example: TRY00
        description:
          type: string
          description: Further details about the payable model
          example: dan@example.com
      required:
        - id
        - type
        - reference
    CauserSummary:
      title: CauserSummary
      type: object
      description: A summary of the model that caused the posting or line to be generated.
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the causer model.
          format: object-id
        type:
          type: string
          description: The type of the causer model.
          enum:
            - basket
            - basket_item
            - payment
            - refund
            - membership_charge
            - voucher_code
        reference:
          type: string
          description: A reference for the causer.
          example: TRY00
      required:
        - id
        - type
    LedgerLine:
      type: object
      title: LedgerLine
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the ledger line.
        gross_amount:
          type: integer
          description: The gross amount of the ledger line.
          example: 10000
        net_amount:
          type: integer
          description: The net amount of the ledger line.
          example: 8333
        type:
          type: string
          description: The type of the ledger line, i.e. a charge (payment or refund) or revenue.
          enum:
            - charge
            - revenue
        description:
          type: string
          description: A description of the ledger line.
          example: Trybe Cash payment [TRY3Z] Jane Jenkins
        revenue_centre:
          type: string
          nullable: true
          description: Contains the revenue centre ID if this line is for revenue.
          example: spa
        revenue_centre_name:
          type: string
          nullable: true
          description: A friendly name for the revenue centre.
          example: Spa
        payment_processor:
          type: string
          nullable: true
          description: A key for the payment processor if this line is for a charge.
          example: manual
        payment_processor_friendly:
          type: string
          nullable: true
          description: A friendly name for the payment processor and type if this line is for a charge.
          example: Manual (Cash)
        mapped_value:
          type: string
          nullable: true
          description: The value that this line's revenue centre or payment processor was mapped to for the integration.
          example: trybe_spa_revenue
        ledger_date:
          type: string
          format: date-time
          description: The date and time the ledger event occurred.
          example: '2023-04-02T00:00:00+01:00'
        currency:
          type: string
          description: The currency of the ledger line. See [Supported Currencies](/endpoints/Meta#metaSupportedCurrencies) for a list of supported currencies.
          example: gbp
        payable:
          $ref: '#/components/schemas/PayableSummary'
          nullable: true
        causer:
          $ref: '#/components/schemas/CauserSummary'
          nullable: true
        status:
          type: string
          description: The status of the ledger line. Lines without a status are assumed to be final.
          nullable: true
          enum:
            - pending
            - final
        created_at:
          type: string
          format: date-time
          description: The date and time the ledger posting was created.
          example: '2023-05-05T11:38:29+01:00'
      required:
        - id
        - gross_amount
        - net_amount
        - type
        - description
        - revenue_centre
        - revenue_centre_name
        - payment_processor
        - payment_processor_friendly
        - ledger_date
        - currency
        - payable
        - causer
        - status
        - created_at
    LedgerLinePosting:
      type: object
      title: LedgerLinePosting
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of this ledger line posting.
        site_id:
          type: string
          description: The ID of the site this ledger line posting belongs to.
          format: uuid
        created_at:
          type: string
          format: date-time
          description: The date and time the ledger posting was created.
          example: '2023-05-05T11:38:29+01:00'
        integration:
          type: string
          description: An identifier for the integration the posting was for.
          example: guestline_rezlynx
        integration_name:
          type: string
          description: A user-friendly name for the integration.
          example: Guestline
        integration_is_async:
          type: boolean
          description: Whether the integration works asynchronously.
          example: false
        status:
          type: string
          description: The status of the posting.
          enum:
            - success
            - resolved
            - error
            - in_progress
            - not_started
            - nothing_to_post
        payable:
          $ref: '#/components/schemas/PayableSummary'
        causer:
          $ref: '#/components/schemas/CauserSummary'
        last_error:
          type: string
          description: The last error encountered when attempting to post this record.
        last_error_at:
          type: string
          format: date-time
          description: The date and time of the last error.
          example: '2023-05-05T11:39:21+01:00'
        succeeded_at:
          type: string
          format: date-time
          description: The date and time the posting succeeded.
          example: '2023-05-05T11:39:21+01:00'
        lines:
          type: array
          items:
            $ref: '#/components/schemas/LedgerLine'
      required:
        - id
        - site_id
        - created_at
        - integration
        - integration_name
        - status
        - payable
        - causer
        - lines
    LedgerLinePostingMeta:
      type: object
      title: LedgerLinePostingMeta
      additionalProperties: false
      properties:
        aggregations:
          type: array
          items:
            title: LedgerLinePostingMetaAggregation
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                example: integrations
                description: The id of this aggregation
              name:
                type: string
                example: Integrations
                description: The friendly name for this aggregation
              options:
                type: array
                description: The options for this aggregation
                items:
                  title: LedgerLinePostingMetaAggregationOption
                  type: object
                  additionalProperties: false
                  properties:
                    id:
                      type: string
                      example: mews
                      description: The id of this aggregation option
                    name:
                      type: string
                      example: Mews
                      description: The friendly name of this aggregation option
                    count:
                      type: integer
                      example: 100
                      description: The count of this aggregation option
        last_succeeded_at:
          type: string
          format: date-time
          description: The date and time a ledger line posting last succeeded
          nullable: true
          example: '2023-05-05T11:39:21+01:00'
        last_error_at:
          type: string
          format: date-time
          description: The date and time a ledger line posting last errored
          nullable: true
          example: '2023-05-05T11:39:21+01:00'
        total_succeeded:
          type: integer
          description: The total number of succeeded postings
          example: 100
        total_errored:
          type: integer
          description: The total number of errored postings
          example: 20
        success_rate:
          type: number
          description: The success rate to 2 decimal places
          example: 99.9
      required:
        - aggregations
        - last_succeeded_at
        - last_error_at
        - total_succeeded
        - total_errored
        - success_rate
    ListLedgerLinePostingsResponse:
      title: ListLedgerLinePostingsResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/LedgerLinePosting'
        meta:
          description: |
            Pagination metadata plus aggregate ledger-posting figures across
            the entire filtered result set (not just the current page) —
            useful for surfacing totals without a separate aggregate call.
          allOf:
            - $ref: '#/components/schemas/PaginationMeta'
            - $ref: '#/components/schemas/LedgerLinePostingMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    ShowLedgerLinePostingResponse:
      type: object
      title: ShowLedgerLinePostingResponse
      additionalProperties: false
      properties:
        data:
          $ref: '#/components/schemas/LedgerLinePosting'
      required:
        - data
    UpdateLedgerLinePosting:
      type: object
      title: UpdateLedgerLinePosting
      additionalProperties: false
      properties:
        status:
          type: string
          description: The status of the LedgerLinePosting
          enum:
            - success
            - resolved
      required:
        - status
    PractitionerRotaAvailabilityRule:
      title: PractitionerRotaAvailabilityRule
      description: A single availability slot within a `PractitionerRota` cycle.
      type: object
      additionalProperties: false
      properties:
        week_num:
          type: integer
          description: The week number within the rota cycle that this rule applies to (1-indexed).
          example: 1
        weekday:
          type: string
          description: The day of the week this rule applies to.
          enum:
            - monday
            - tuesday
            - wednesday
            - thursday
            - friday
            - saturday
            - sunday
          example: monday
        time_from:
          type: string
          description: The start time of the availability window in HH:MM format.
          example: '09:00'
        time_to:
          type: string
          description: The end time of the availability window in HH:MM format.
          example: '17:00'
        offerings:
          type: array
          description: |
            The offerings the practitioner is assigned to during this window.
            An empty array means the practitioner is not linked to specific
            offerings for this window.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
      required:
        - week_num
        - weekday
        - time_from
        - time_to
    PractitionerRota:
      title: PractitionerRota
      description: A `PractitionerRota` defines a practitioner's recurring availability schedule over a date range.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the rota.
        practitioner_id:
          type: string
          format: object-id
          description: The ID of the practitioner this rota belongs to.
        start_date:
          type: string
          format: date-time
          nullable: true
          description: The date from which this rota is active.
        end_date:
          type: string
          format: date-time
          nullable: true
          description: The date on which this rota ends. Null indicates an open-ended rota.
        scheduling_week_interval:
          type: integer
          description: The number of weeks in the rolling schedule cycle (e.g. 2 for a fortnightly rota).
          example: 2
        availability_rules:
          type: array
          description: The availability rules that define when the practitioner is available within the rota cycle.
          items:
            $ref: '#/components/schemas/PractitionerRotaAvailabilityRule'
      required:
        - id
        - practitioner_id
        - start_date
        - end_date
        - scheduling_week_interval
        - availability_rules
    PractitionerTag:
      title: PractitionerTag
      description: |
        A `PractitionerTag` is a free-form label that can be attached to
        one or more `Practitioner`s within an organisation. Tags are used
        to group practitioners for reporting, filtering in the calendar,
        and assigning to offerings that require particular skills (e.g.
        `Senior Therapist`, `Sports Massage`, `Bilingual — French`).

        Tags are scoped to the `Organisation` rather than to an individual
        `Site`, so the same tag can be applied to practitioners across
        every site in the organisation.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the tag.
          example: 5f1234567890abcdef123456
        name:
          type: string
          description: |
            Display name for the tag, shown wherever practitioners are
            listed or filtered. Plain text only; emoji is allowed but
            rendering is up to the consumer.
          example: Senior Therapist
        organisation_id:
          type: string
          format: uuid
          description: |
            ID of the organisation that owns the tag. On create, defaults
            to the caller's default organisation when omitted.
          example: 22222222-2222-2222-2222-222222222222
      required:
        - id
        - name
        - organisation_id
    PractitionerAppointmentRestriction:
      title: PractitionerAppointmentRestriction
      description: A single appointment restriction that applies to a practitioner.
      type: object
      additionalProperties: false
      required:
        - id
        - applies_to_type
        - date_from
        - date_to
      properties:
        id:
          type: string
          description: The ID of the restriction
          example: 5dcb47800000000000000011
        applies_to_type:
          type: string
          description: The type of the restriction
          enum:
            - specific
            - categories
        appointment_type_ids:
          type: array
          description: The IDs of appointment types that this restriction applies to
          items:
            type: string
            example: 5dcb47800000000000000010
        appointment_types:
          description: The appointment types associated with this product
          type: array
          items:
            title: PractitionerAppointmentRestrictionAppointmentType
            type: object
            additionalProperties: false
            required:
              - id
              - name
            properties:
              id:
                type: string
              name:
                type: string
        categories:
          description: The category associated with this product
          type: array
          items:
            title: PractitionerAppointmentRestrictionCategory
            type: object
            additionalProperties: false
            required:
              - id
              - name
            properties:
              id:
                type: string
              name:
                type: string
        category_ids:
          type: array
          description: The IDs of categories that this restriction applies to
          items:
            type: string
            example: 5dcb47800000000000000010
        date_from:
          type: string
          format: date
          description: The first day that this restriction should apply
          example: '2020-06-20'
        date_to:
          type: string
          format: date
          description: The last date that this restriction should apply
          example: '2020-06-20'
        max_duration:
          type: integer
          description: For a `max_duration` rule, this specifies the maximum number of minutes of the appointment type that the practitioner may offer each day.
          example: 180
        occupied_mins:
          type: integer
          example: 60
        type:
          type: string
          description: The type of the restriction
          enum:
            - cannot_offer
            - max_duration
    Practitioner:
      title: Practitioner
      description: A bookable staff member — typically a therapist, instructor or stylist — that appointments and sessions can be assigned to. Practitioners own a working rota, optional commission rules, and the set of session/appointment types they are qualified to deliver.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: |
            Stable identifier for the practitioner. Used when assigning
            sessions, appointments and rotas to the practitioner, and when
            the booking storefront resolves a slot to a specific staff
            member.
          example: 5dcb47800000000000000000
        appointment_restrictions:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerAppointmentRestriction'
        avatar:
          $ref: '#/components/schemas/Media'
        signature:
          description: |
            `Media` to use as the practitioner's signature image. Shown
            on documents and receipts that require a practitioner
            signature. Absent when no signature has been uploaded.
          $ref: '#/components/schemas/Media'
        can_offer_tags:
          type: array
          items:
            type: string
        gender:
          type: string
          nullable: true
          description: |
            Self-identified gender of the practitioner, surfaced to guests
            who filter the booking storefront by practitioner gender. Free
            text — common values are `female`, `male` and `non-binary`.
            `null` when the practitioner hasn't supplied a value.
          example: female
        name:
          type: string
          description: |
            Public display name of the practitioner. Shown to guests on
            the booking storefront and on receipts. Should be the name the
            practitioner wants to appear in front of guests — typically
            first name plus last initial or full name.
          example: Jane Doe
        registration_number:
          type: string
          nullable: true
          description: |
            Optional registration or license number for the practitioner.
            Used to track professional credentials or qualifications.
          example: A123
        organisation_id:
          type: string
          format: uuid
          description: |
            Organisation the practitioner belongs to. Practitioners are
            scoped to a single organisation and are not visible to API
            callers from other organisations.
          example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
        site_ids:
          type: array
          items:
            type: string
            format: uuid
        tag_ids:
          type: array
          items:
            type: string
        tags:
          type: array
          items:
            $ref: '#/components/schemas/Tag'
        zones:
          type: array
          items:
            $ref: '#/components/schemas/Zone'
        commission_package_id:
          type: string
          format: mongo-id
          description: |
            The commission package to use for this practitioner. If not set, the practitioner's default commission package will be the site's default commission package (as defined by `ShopSite.default_commission_package_id`).
          nullable: true
        external_id:
          type: string
          nullable: true
          description: |
            Optional external identifier for the practitioner, used to
            correlate this record with an entry in a third-party system
            (e.g. a PMS, payroll provider, or CRM). Not interpreted by
            the platform — treated as an opaque string.
          example: EXT-001
        user_id:
          type: string
          format: uuid
          nullable: true
          description: |
            Staff `User` linked to this practitioner record, if any.
            Linking lets the user manage their own rota and view their
            appointments from the staff console. `null` for practitioners
            that don't have a login account.
          example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - appointment_restrictions
        - can_offer_tags
        - external_id
        - name
        - organisation_id
        - site_ids
        - tag_ids
        - tags
        - zones
        - user_id
        - created_at
        - updated_at
    PractitionerAppointmentRestrictionAppointmentType:
      title: PractitionerAppointmentRestrictionAppointmentType
      description: A minimal summary of an `AppointmentType` referenced by a `PractitionerAppointmentRestriction`.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the appointment type.
        name:
          type: string
          description: The display name of the appointment type.
          example: Deep Tissue Massage
      required:
        - id
        - name
    PractitionerAppointmentRestrictionCategory:
      title: PractitionerAppointmentRestrictionCategory
      description: A minimal summary of a `Category` referenced by a `PractitionerAppointmentRestriction`.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the category.
        name:
          type: string
          description: The name of the category.
          example: Massages
      required:
        - id
        - name
    schemas_PractitionerAppointmentRestriction:
      title: PractitionerAppointmentRestriction
      description: |
        A `PractitionerAppointmentRestriction` records a constraint on the
        appointments a practitioner can take. Restrictions can either block
        the practitioner from a set of appointment types entirely
        (`type: cannot_offer`) or cap the duration of appointments they are
        allowed to take (`type: max_duration`).

        Restrictions can apply to a hand-picked list of appointment types
        (`applies_to_type: specific`) or to every appointment type in one
        or more categories (`applies_to_type: categories`). They can
        optionally be limited to a date range; outside that range the
        restriction has no effect.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The unique identifier of the restriction.
        type:
          type: string
          description: |
            The kind of restriction this rule applies. `cannot_offer`
            prevents the practitioner from taking matching appointments
            at all; `max_duration` caps how long matching appointments
            can be.
          enum:
            - cannot_offer
            - max_duration
          example: cannot_offer
        applies_to_type:
          type: string
          description: |
            How the restriction picks which appointment types it covers.
            `specific` matches against `appointment_type_ids`;
            `categories` matches every appointment type linked to one of
            the listed `category_ids`.
          enum:
            - specific
            - categories
          example: specific
        appointment_type_ids:
          type: array
          description: |
            IDs of the `AppointmentType`s this restriction applies to.
            Only present when `applies_to_type` is `specific`.
          items:
            type: string
            format: object-id
        appointment_types:
          type: array
          description: |
            Inline summaries of the appointment types referenced by
            `appointment_type_ids`. Only present when `applies_to_type`
            is `specific`.
          items:
            $ref: '#/components/schemas/PractitionerAppointmentRestrictionAppointmentType'
        category_ids:
          type: array
          description: |
            IDs of the `Category`s this restriction applies to. Only
            present when `applies_to_type` is `categories`.
          items:
            type: string
            format: object-id
        categories:
          type: array
          description: |
            Inline summaries of the categories referenced by
            `category_ids`. Only present when `applies_to_type` is
            `categories`.
          items:
            $ref: '#/components/schemas/PractitionerAppointmentRestrictionCategory'
        date_from:
          type: string
          format: date
          nullable: true
          description: |
            First date the restriction applies (inclusive), in the
            practitioner's timezone. `null` means it applies from any
            date in the past.
          example: '2026-06-01'
        date_to:
          type: string
          format: date
          nullable: true
          description: |
            Last date the restriction applies (inclusive), in the
            practitioner's timezone. `null` means it has no end date.
          example: '2026-08-31'
        max_duration:
          type: integer
          nullable: true
          description: |
            Maximum appointment duration the practitioner can take, in
            minutes. Only present when `type` is `max_duration`.
          example: 60
        occupied_mins:
          type: integer
          description: |
            Optional context value: minutes already occupied by other
            bookings during the restriction's window. Present only when
            the restriction was loaded with availability context.
          example: 30
      required:
        - id
        - type
        - applies_to_type
        - date_from
        - date_to
    PractitionerCustomAvailability:
      title: PractitionerCustomAvailability
      description: |
        A `PractitionerCustomAvailability` is an ad-hoc override to a
        practitioner's regular rota for a specific date-time window.
        Setting `is_available: true` opens an extra working window — for
        example, picking up a Saturday shift; `is_available: false`
        blocks the practitioner from being booked — for example, leave
        or sickness.

        Custom availability rules take precedence over the rota for the
        period they cover. Adjacent rules with the same `is_available`
        value, `room_id`, `category_ids`, and `offerings` are automatically
        merged when created or updated.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The unique identifier of the custom availability rule.
        has_availability_id:
          type: string
          format: object-id
          description: The ID of the resource this rule belongs to. For rules created through this endpoint, this is the practitioner ID.
        date_time_from:
          type: string
          format: date-time
          description: The start of the window the rule covers, in ISO 8601 with the practitioner's timezone offset.
          example: '2026-06-01T09:00:00+01:00'
        date_time_to:
          type: string
          format: date-time
          description: The end of the window the rule covers, in ISO 8601 with the practitioner's timezone offset.
          example: '2026-06-01T17:00:00+01:00'
        is_available:
          type: boolean
          description: |
            `true` means the practitioner is bookable during the window;
            `false` blocks bookings. A `false` rule overrides any
            regular rota availability for the same period.
        room_id:
          type: string
          format: object-id
          nullable: true
          description: The ID of the room the practitioner is assigned to during this window, if any.
        category_ids:
          type: array
          description: The IDs of the service categories the practitioner is available for during this window. An empty array means all categories are available.
          items:
            type: string
            format: object-id
        offerings:
          type: array
          description: The offerings the practitioner is assigned to during this window. An empty array means the practitioner is not linked to specific offerings for this window.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
      required:
        - id
        - has_availability_id
        - date_time_from
        - date_time_to
        - is_available
        - room_id
        - category_ids
        - offerings
    RoomTag:
      title: RoomTag
      description: |
        A `RoomTag` is a free-form label that can be attached to one or
        more `Room`s within an organisation. Tags are used to group rooms
        for reporting and to assign appointment types to a pool of
        equivalently-equipped rooms (e.g. `Couples Room`, `Hydrotherapy`,
        `Wet Room`).

        Tags are scoped to the `Organisation` rather than to an individual
        `Site`, so the same tag can be applied to rooms across every site
        in the organisation.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the tag.
          example: 5f1234567890abcdef123456
        name:
          type: string
          description: |
            Display name for the tag, shown wherever rooms are listed or
            filtered. Plain text only; emoji is allowed but rendering is
            up to the consumer.
          example: Couples Room
        organisation_id:
          type: string
          format: uuid
          description: |
            ID of the organisation that owns the tag. On create, defaults
            to the caller's default organisation when omitted.
          example: 22222222-2222-2222-2222-222222222222
      required:
        - id
        - name
        - organisation_id
    TaxRate:
      type: object
      title: TaxRate
      additionalProperties: false
      properties:
        name:
          type: string
          description: A name for the tax rate.
          example: VAT
        percentage:
          type: number
          description: The percentage of tax that should be applied
          example: 17.5
        basis:
          type: string
          description: |
            The base amount on which the tax should be calculated. If cumulative then the tax will be calculated
            based on the net amount plus the amount of all previous tax rates in the current tax set.
          enum:
            - net
            - cumulative
        inclusive:
          type: boolean
          description: Whether the price the customer sees includes this tax amount.
      required:
        - name
        - percentage
        - basis
        - inclusive
    RateSet:
      type: object
      title: TaxSet
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: An ID for the tax set.
        valid_from:
          type: string
          format: date-time
          description: The date and time after which this tax set should apply.
          nullable: true
        valid_to:
          type: string
          format: date-time
          description: The date and time until which this tax set should apply.
          nullable: true
        tax_rates:
          type: array
          description: The tax rates that should be applied when this tax rate is valid.
          items:
            $ref: '#/components/schemas/TaxRate'
      required:
        - id
        - valid_from
        - valid_to
        - tax_rates
    TaxConfiguration:
      type: object
      title: TaxConfiguration
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the tax configuration.
        name:
          type: string
          description: A name for the tax configuration.
          example: UK VAT
        description:
          type: string
          description: An optional description of the tax configuration.
          example: Applies to most items sold in the UK
          nullable: true
        rate_sets:
          type: array
          description: The percentage of tax to be applied for this revenue centre.
          items:
            $ref: '#/components/schemas/RateSet'
      required:
        - id
        - name
        - description
        - rate_sets
    amount:
      type: string
      format: integer
      description: Test the tax configuration with the given customer-facing amount.
    date:
      type: string
      format: date-time
      description: Test the tax configuration as it would be applied on the given date.
      nullable: true
    CalculatedTax:
      type: object
      title: CalculatedTax
      additionalProperties: false
      properties:
        name:
          type: string
          description: The name of the applied tax rate.
          example: VAT
        inclusive:
          type: string
          description: Whether this tax amount is included in the item_amount that the customer is presented with.
          example: true
        basis:
          type: string
          description: The base amount on which this tax was calculated.
          enum:
            - net
            - cumulative
        percentage:
          type: number
          description: The percentage of this tax.
          example: 20
        amount:
          type: integer
          description: The calculated amount of this tax.
          example: 1667
        base_amount:
          type: integer
          description: The base amount on which this tax was calculated.
          example: 8333
        item_amount:
          type: integer
          description: The price of the item as it would be presented to the customer before any taxes have been added.
          example: 10000
        included_remainder:
          type: integer
          description: A remainder amount if any was included in this tax rate as a result of rounding differences.
          example: 1
      required:
        - name
        - inclusive
        - basis
        - percentage
        - amount
        - base_amount
        - item_amount
        - included_remainder
    TaxCalculation:
      type: object
      title: TaxCalculation
      additionalProperties: false
      properties:
        net_amount:
          type: integer
          description: The calculated pre-tax amount for the given amount, after any inclusive taxes have been removed.
          example: 1667
        gross_amount:
          type: integer
          description: The calculated post-tax amount for the given amount, after any exclusive taxes have been added.
          example: 10000
        taxes:
          type: array
          items:
            $ref: '#/components/schemas/CalculatedTax'
    IntegrationSettings:
      title: IntegrationSettings
      additionalProperties: false
      type: object
      description: Integration settings associated with this visit type.
      properties:
        auto_send_portal_invite_notification:
          type: boolean
          description: Flag to indicate if portal invite notifications are automatically sent.
          example: true
          nullable: true
    VisitType:
      type: object
      title: VisitType
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of this visit configuration.
          format: object-id
        name:
          type: string
          description: A name to identify this visit configuration, for internal use.
          example: Spa Weekend
        description:
          type: string
          description: A description of this visit configuration, for internal use.
          example: To be offered to guests staying in December.
        offerings:
          type: array
          description: An array of offerings which each guest can choose from. Each guest may choose one of the following.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        email_settings:
          title: EmailSettings
          additionalProperties: false
          type: object
          description: Email settings associated with this visit type.
          properties:
            creation_email_message:
              type: string
              description: Message sent when a visit is created. When null, the platform default message will be used.
              example: Your visit has been created.
              nullable: true
            reminder_emails_enabled:
              type: boolean
              description: Flag to indicate if reminder emails are enabled.
              example: true
            reminder_emails_message:
              type: string
              description: Reminder message for the upcoming visit.
              example: This is a reminder for your upcoming visit.
              nullable: true
            reminder_emails_time:
              type: string
              description: Time to send the reminder emails. The time is relative to the site's local timezone.
              example: '09:00'
              nullable: true
            reminder_emails_days_ahead:
              type: integer
              description: Number of days ahead to send the reminder email.
              example: 2
              nullable: true
          required:
            - creation_email_message
            - reminder_emails_enabled
            - reminder_emails_message
            - reminder_emails_time
            - reminder_emails_days_ahead
        rate_codes:
          type: array
          description: An array of unique rate codes associated with this visit type. Each code must be unique across all visit types.
          items:
            type: string
            example: RATE10
          nullable: true
        integration_settings:
          $ref: '#/components/schemas/IntegrationSettings'
      required:
        - id
        - name
        - description
        - offerings
        - email_settings
        - rate_codes
        - integration_settings
    VoucherType:
      title: VoucherType
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the voucher type.
        name:
          type: string
          description: The name of this voucher type.
          example: £50 voucher
        description:
          type: string
          description: A description of the voucher type.
          example: £50 off a treatment of your choice.
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering.
        product_code:
          type: string
          description: A custom product code for the voucher type.
          example: VOU123
        image:
          $ref: '#/components/schemas/Media'
        recipient_message:
          type: string
          description: A message that will be included in the email containing the gift voucher.
          example: You can spend this on anything you like. Enjoy!
        hide_redemption_instructions:
          type: boolean
          description: |
            When `true`, the "Use your voucher" button and instructions paragraph are
            omitted from the gift-voucher email. Useful for vouchers that are redeemed
            outside of Trybe (e.g. free items not sold through the shopfront), where
            sending recipients to the shopfront lookup would result in a 404.
          example: false
        amount_type:
          type: string
          description: The type of discount offered by this voucher.
          enum:
            - cash
            - discount_to_zero
        amount:
          type: integer
          description: The value of this voucher if it is a 'cash' type
          example: 2500
        customisable_amount:
          type: boolean
          description: Whether the amount of this voucher can be overridden by a user when it is being sold
          example: true
        customer_customisable_amount:
          type: boolean
          description: |
            When true, customers can enter their own amount when purchasing this
            voucher online. Only relevant when `amount_type=cash`.
          example: false
        minimum_custom_amount:
          type: integer
          nullable: true
          description: |
            The minimum amount (in the voucher's minor currency unit, e.g. pence)
            that a customer may enter when `customer_customisable_amount` is `true`.
            When `null`, the system-wide minimum applies (currently 500, i.e. £5.00).
            Must be >= the system minimum. Only relevant when `amount_type=cash`.
          example: 1000
        valid_weekdays:
          type: array
          description: An array of weekdays (in lowercase) that this voucher may be used on.
          items:
            type: string
            example: monday
        invalid_date_set_ids:
          type: array
          description: An array of date set IDs that this voucher may not be used on.
          items:
            type: string
            format: object-id
        valid_offerings:
          type: array
          description: An array of offerings this voucher may be used on.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        invalid_offerings:
          type: array
          description: If no `valid_offerings` are defined, this is an array of offerings this voucher may _not_ be used on.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        quantity:
          type: integer
          nullable: true
          description: |
            For `discount_to_zero` vouchers only. When set to a value greater than 1,
            a single issued code may be redeemed this many times — once per booking —
            before it is considered fully redeemed. `null` or `1` means single-use.
            Not applicable to `cash` vouchers.
          example: 7
        per_use_value:
          type: integer
          nullable: true
          description: |
            For multi-use `discount_to_zero` vouchers only. The fixed amount (in the
            voucher's minor currency unit) posted to the ledger per redemption, and
            the maximum this voucher will cover per use. Items priced above this
            value require partial payment from the customer. Required when
            `quantity` is greater than 1.
          example: 5000
        partially_redeemable:
          type: boolean
          description: Whether vouchers of this type should be partially redeemable.
          example: true
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this voucher type, in the smallest
            currency unit (e.g. pence). `null` if a standard price hasn't
            been configured — this is distinct from a price of zero.
          example: 5000
        default_validity_interval:
          type: string
          description: The default duration this voucher is valid for, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1Y
        offered_online:
          type: boolean
          description: Whether this voucher type is allowed to be purchased online.
          example: true
        private:
          type: boolean
          description: Whether this is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
        members_only:
          type: boolean
          description: Whether this voucher type requires an active membership in order to purchase.
          example: true
        permitted_membership_type_ids:
          type: array
          description: |
            If this voucher type is for members only, this property may be used to restrict the offering further
            so it may only be purchased by active members with of one of the given membership types.
          items:
            type: string
        availability_rules:
          type: array
          description: The rules defining periods during which the voucher can be purchased.
          items:
            $ref: '#/components/schemas/AvailabilityRule'
        currency:
          type: string
          description: The ISO-4217 currency code in lower case.
          example: gbp
        site_id:
          type: string
          format: uuid
          description: The ID of the site this voucher type belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this voucher type belongs to.
        category_ids:
          type: array
          items:
            type: string
          description: The category IDs associated with this session type
        updated_at:
          type: string
          format: date-time
          description: The time and date that the voucher type was last updated.
          example: '2020-02-24T12:00:00+01:00'
        deleted_at:
          type: string
          format: date-time
          description: The time and date that the voucher type was archived.
          example: '2020-02-24T12:00:00+01:00'
        visibility:
          $ref: '#/components/schemas/visibility'
      required:
        - id
        - name
        - description
        - external_id
        - product_code
        - image
        - recipient_message
        - hide_redemption_instructions
        - amount_type
        - amount
        - customisable_amount
        - valid_weekdays
        - invalid_date_set_ids
        - valid_offerings
        - invalid_offerings
        - partially_redeemable
        - standard_price
        - default_validity_interval
        - offered_online
        - private
        - members_only
        - permitted_membership_type_ids
        - availability_rules
        - price_rules
        - currency
        - site_id
        - organisation_id
        - category_ids
        - visibility
    VoucherMembershipOfferingDetails:
      title: VoucherMembershipOfferingDetails
      description: |
        Extra metadata attached to a `valid_offerings` entry when the
        offering is a membership. Captures which membership type and rate
        the voucher grants, plus the duration of the granted membership.
      type: object
      additionalProperties: false
      properties:
        membership_type_id:
          type: string
          format: uuid
          description: The ID of the granted `MembershipType`.
          example: 9c8b7a6d-5e4f-3210-9876-543210fedcba
        membership_type_name:
          type: string
          description: Display name of the granted membership type.
          example: Wellness Club Gold
        membership_rate_id:
          type: string
          format: uuid
          description: The ID of the rate within `membership_type_id` to grant.
          example: a1b2c3d4-e5f6-7890-1234-567890abcdef
        membership_rate_name:
          type: string
          description: Display name of the granted rate.
          example: Annual rolling
        duration:
          type: string
          description: |
            Length of the granted membership as an ISO 8601 duration.
          example: P1Y
        duration_friendly:
          type: string
          description: |
            Human-readable rendering of `duration` for UI display.
          example: 1 year
      required:
        - membership_type_id
        - membership_type_name
        - membership_rate_id
        - membership_rate_name
        - duration
        - duration_friendly
    VoucherValidOffering:
      title: VoucherValidOffering
      description: |
        A single offering the voucher may be redeemed against. Returned
        enriched with the offering's display name on `getVoucher` and the
        mutation endpoints; on list endpoints only `offering_id` and
        `offering_type` are populated.

        For `offering_type=Membership` the entry also carries an
        `offering_details` block with the resolved membership type, rate,
        and duration.
      type: object
      additionalProperties: false
      properties:
        offering_id:
          type: string
          description: |
            The ID of the offering. For most offering types this is the
            MongoDB `_id` of the offering. For `Membership` offerings, the
            ID is a synthetic composite of the form
            `{membership_type_id}_{membership_rate_id}_{duration}`.
          example: 65f0a1b2c3d4e5f6a7b8c9d1
        offering_type:
          type: string
          description: |
            Display-friendly type label of the offering, capitalised. Maps
            one-to-one to the underlying offering class (e.g. `Session`,
            `AppointmentType`, `Package`, `Membership`).
          example: AppointmentType
        offering_name:
          type: string
          description: The customer-facing name of the offering.
          example: 60-minute Aromatherapy Massage
        offering_details:
          $ref: '#/components/schemas/VoucherMembershipOfferingDetails'
      required:
        - offering_id
        - offering_type
    Voucher:
      title: Voucher
      description: |
        A `Voucher` is the catalogue-level record for a third-party gift
        voucher (e.g. a GiftPro voucher) that has been imported into Trybe
        and made redeemable at a site. Each `Voucher` represents one product
        in the external system — its name, monetary value, currency, and the
        rules constraining where it may be redeemed (allowed offerings,
        permitted weekdays, blackout date sets).

        `Voucher`s are distinct from `VoucherType`s: a `VoucherType` is a
        Trybe-native voucher product that can be sold through the basket and
        issues `VoucherCode`s on purchase; a `Voucher` is an external,
        pre-issued product whose redemption is brokered through a
        `VoucherIntegration` (e.g. GiftPro). The two share a similar runtime
        redemption flow but are managed via separate endpoints.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The Trybe ID of the voucher record.
          example: 65f0a1b2c3d4e5f6a7b8c9d0
        name:
          type: string
          description: |
            Customer- and cashier-facing name of the voucher, mirrored from
            the source system at import time.
          example: Twilight Spa Day Gift Voucher
        description:
          type: string
          nullable: true
          description: |
            Long-form description of the voucher imported from the source
            system. Shown to cashiers when redeeming.
          example: A 90-minute treatment, lunch, and full access to the spa facilities.
        processor_voucher_id:
          type: string
          description: |
            The voucher's primary key in the external processor's system
            (e.g. the GiftPro voucher ID). Used to reconcile the Trybe
            record with the source of truth.
          example: gp_8421
        price:
          type: integer
          description: |
            The face value of the voucher in the smallest unit of
            `currency` (e.g. pence for `gbp`). Mirrored from the source
            system and used as the redemption amount when the voucher is
            presented as payment.
          example: 12500
        currency:
          type: string
          description: |
            The ISO-4217 currency code (lowercase) the voucher's `price` is
            expressed in.
          example: gbp
        processor:
          type: string
          description: |
            Identifier of the integration that owns this voucher. Drives
            which redemption flow Trybe routes the voucher through at
            checkout.
          example: giftpro
        processor_data:
          type: object
          description: |
            Processor-specific metadata captured at import time. Shape
            varies by `processor`; treat as opaque unless you specifically
            target a known integration.
          additionalProperties: true
          example: {}
        valid_offerings:
          type: array
          description: |
            Offerings the voucher may be redeemed against. When the
            endpoint is called with offering summaries enabled (the default
            for `getVoucher` and the mutation endpoints), each entry is
            enriched with the offering's display name. When empty, the
            voucher is redeemable against any offering subject to the
            site's normal rules.
          items:
            $ref: '#/components/schemas/VoucherValidOffering'
        valid_weekdays:
          type: array
          description: |
            Lowercase weekday names the voucher may be redeemed on. Empty
            means "any weekday".
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
          example:
            - monday
            - tuesday
            - wednesday
            - thursday
            - friday
        invalid_date_set_ids:
          type: array
          description: |
            IDs of date sets (e.g. bank holidays, peak-season blackouts) on
            which the voucher may **not** be redeemed. Each ID must
            reference a date set on the caller's organisation.
          items:
            type: string
            format: object-id
          example:
            - 65f0a1b2c3d4e5f6a7b8c9aa
        site_id:
          type: string
          format: uuid
          description: The ID of the site this voucher record belongs to.
          example: 1f3c0e2a-9b8d-4c5e-a6f7-1234567890ab
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation that owns the voucher record.
          example: 0a1b2c3d-4e5f-6789-abcd-ef0123456789
        processor_created_at:
          type: string
          format: date-time
          nullable: true
          description: When the voucher was created in the source processor's system.
          example: '2025-12-15T09:30:00+00:00'
        created_at:
          type: string
          format: date-time
          description: When the voucher record was imported into Trybe.
          example: '2026-01-04T11:00:00+00:00'
        updated_at:
          type: string
          format: date-time
          description: When the voucher record was last updated in Trybe.
          example: '2026-04-22T14:18:00+00:00'
      required:
        - id
        - name
        - description
        - processor_voucher_id
        - price
        - currency
        - processor
        - processor_data
        - valid_offerings
        - valid_weekdays
        - invalid_date_set_ids
        - site_id
        - organisation_id
        - processor_created_at
        - created_at
        - updated_at
    VoucherCodeLookupOffering:
      title: VoucherCodeLookupOffering
      description: |
        A single offering returned in the `valid_offerings` array of the
        voucher-code lookup response. Includes both raw IDs and a
        pre-formatted `display_name` suitable for direct UI rendering.
      type: object
      additionalProperties: false
      properties:
        offering_type:
          type: string
          description: |
            Snake-case type discriminator (e.g. `appointment`, `session`,
            `package`, `membership`).
          example: appointment
        offering_id:
          type: string
          description: The ID of the offering.
          example: 65f0a1b2c3d4e5f6a7b8c9d4
        offering_name:
          type: string
          description: |
            The plain display name of the offering, resolved from the
            offering's `name` if necessary.
          example: 60-minute Aromatherapy Massage
        display_name:
          type: string
          description: |
            A pre-formatted display name for the offering — identical to
            `offering_name` for non-membership offerings, augmented with the
            granted duration for `membership` offerings (e.g. `Wellness
            Club Gold (1 year)`).
          example: 60-minute Aromatherapy Massage
        offering_config:
          type: object
          description: |
            Offering-type-specific configuration. Present only when the
            offering needs extra metadata at redemption time — currently
            only `membership` offerings, where the block carries the
            granted duration.
          additionalProperties: true
          example:
            duration: P1Y
      required:
        - offering_type
        - offering_id
        - offering_name
        - display_name
    VoucherCodeLookup:
      title: VoucherCodeLookup
      description: |
        The runtime view of a voucher code returned by `checkVoucherCode`.
        Carries the redeemable balance, validity window, owning voucher
        type or external voucher, and the list of offerings the code may
        be redeemed against. The payload shape varies slightly depending on
        whether the code is a Trybe-native `VoucherCode` or an
        integration-issued external voucher (e.g. GiftPro) — see the
        `payment_processor` discriminator.
      type: object
      additionalProperties: true
      properties:
        id:
          type: string
          format: object-id
          description: |
            The ID of the Trybe `VoucherCode`. Omitted for external
            vouchers — use `processor_voucher_id` instead.
          example: 65f0a1b2c3d4e5f6a7b8c9d2
        code:
          type: string
          description: The redemption code itself, as quoted by the customer.
          example: SUMMER2026-X9K2
        payment_processor:
          type: string
          description: |
            Discriminator identifying which redemption flow applies.
            `voucher` is a Trybe-native code, `external_voucher` is an
            integration-issued code that will be reconciled with the
            external processor at redemption time.
          enum:
            - voucher
            - external_voucher
          example: voucher
        processor_voucher_id:
          type: string
          nullable: true
          description: |
            For external vouchers, the voucher's primary key in the source
            processor's system. Omitted for Trybe-native codes.
          example: gp_8421
        processor:
          type: string
          nullable: true
          description: |
            For external vouchers, the integration that issued the code
            (e.g. `giftpro`). Omitted for Trybe-native codes.
          example: giftpro
        valid_from_date:
          type: string
          format: date-time
          nullable: true
          description: The earliest date the code may be redeemed.
          example: '2026-01-01T00:00:00+00:00'
        valid_to_date:
          type: string
          format: date-time
          nullable: true
          description: |
            The latest date the code may be redeemed. `null` indicates the
            code does not expire.
          example: '2027-01-01T00:00:00+00:00'
        amount_type:
          type: string
          description: |
            Whether the code carries a fixed cash value (`cash`) or
            discounts the order it is redeemed against to zero
            (`discount_to_zero`). External vouchers are always reported as
            `cash`.
          enum:
            - cash
            - discount_to_zero
          example: cash
        total:
          type: integer
          description: |
            The original face value of the code, in the smallest unit of
            `currency`.
          example: 5000
        balance:
          type: integer
          description: |
            The remaining redeemable balance, in the smallest unit of
            `currency`. For `discount_to_zero` vouchers, reports `0` once
            the voucher has been redeemed.
          example: 2500
        currency:
          type: string
          description: The ISO-4217 currency code (lowercase).
          example: gbp
        partially_redeemable:
          type: boolean
          description: |
            Whether the remaining balance can be split across multiple
            redemptions. `discount_to_zero` vouchers are never partially
            redeemable.
          example: true
        uses_total:
          type: integer
          nullable: true
          description: |
            For multi-use `discount_to_zero` codes only: the total number of
            redemptions the code allows. `null` when the parent `VoucherType`
            has `quantity` of `null` or `1`, and for all `cash` vouchers.
          example: 7
        uses_remaining:
          type: integer
          nullable: true
          description: |
            For multi-use `discount_to_zero` codes only: how many redemptions
            are still available. `null` when the parent `VoucherType` has
            `quantity` of `null` or `1`, and for all `cash` vouchers.
          example: 5
        voucher_name:
          type: string
          nullable: true
          description: |
            The display name of the parent `VoucherType` (for Trybe-native
            codes) or `Voucher` (for external codes). May be `null` for
            external codes that could not be matched back to a Trybe
            `Voucher` record.
          example: £50 Gift Voucher
        customer_id:
          type: string
          format: object-id
          nullable: true
          description: |
            The ID of the customer the code was issued to, if known.
            Omitted for external vouchers.
          example: 65f0a1b2c3d4e5f6a7b8c9d3
        fulfillment_status:
          type: string
          nullable: true
          description: |
            Fulfilment status of the voucher (e.g. `needs_dispatching`,
            `dispatched`, `not_required`). Omitted for external vouchers.
          example: dispatched
        value:
          type: integer
          description: |
            Alias of `total`, retained for backwards compatibility with
            older clients. Omitted for external vouchers.
          example: 5000
        valid_offerings:
          type: array
          description: |
            The offerings the code may be redeemed against. Includes
            offering display names and offering-type-specific configuration
            (e.g. for membership vouchers, the duration of the granted
            membership).
          items:
            $ref: '#/components/schemas/VoucherCodeLookupOffering'
      required:
        - code
        - payment_processor
        - valid_from_date
        - valid_to_date
        - amount_type
        - total
        - balance
        - currency
        - partially_redeemable
        - uses_total
        - uses_remaining
        - voucher_name
        - valid_offerings
    UpdateVoucherValidOfferingMembershipDetails:
      title: UpdateVoucherValidOfferingMembershipDetails
      description: |
        Membership-specific configuration. **Required when
        `offering_type=membership`**, ignored otherwise. The server resolves
        the membership type and rate at request time and returns the
        looked-up display names in the response.
      type: object
      additionalProperties: false
      properties:
        membership_type_id:
          type: string
          format: uuid
          description: The granted `MembershipType`.
          example: 9c8b7a6d-5e4f-3210-9876-543210fedcba
        membership_rate_id:
          type: string
          format: uuid
          description: The granted rate within `membership_type_id`.
          example: a1b2c3d4-e5f6-7890-1234-567890abcdef
        duration:
          type: string
          description: |
            Length of the granted membership as an ISO 8601 duration (e.g.
            `P1Y` for 1 year, `P6M` for 6 months).
          example: P1Y
      required:
        - membership_type_id
        - membership_rate_id
        - duration
    UpdateVoucherValidOffering:
      title: UpdateVoucherValidOffering
      description: |
        A single entry in the `valid_offerings` allowlist sent on
        `updateVoucher`. For non-membership offerings only `offering_id`
        and `offering_type` are needed; for `offering_type=membership` the
        `offering_details` block is required and the server synthesises
        `offering_id` from it.
      type: object
      additionalProperties: false
      properties:
        offering_id:
          type: string
          description: |
            The ID of the offering. For most offering types this is the
            offering's MongoDB `_id`. For `offering_type=membership` the
            server resolves the composite ID from `offering_details` and
            ignores any value passed here.
          example: 65f0a1b2c3d4e5f6a7b8c9d4
        offering_type:
          type: string
          description: |
            Snake-case type of the offering. Mirrors the values accepted
            by the offering allowlist on a `VoucherType`.
          enum:
            - appointment
            - area_booking
            - course
            - hotel_room_reservation
            - membership
            - package
            - product
            - session
            - table_reservation
          example: appointment
        offering_details:
          $ref: '#/components/schemas/UpdateVoucherValidOfferingMembershipDetails'
      required:
        - offering_id
        - offering_type
    has_password:
      type: boolean
      description: Whether the user has a password
      example: true
    dob:
      type: string
      format: date
      description: The customer's date of birth in YYYY-MM-DD format, or `null` if not provided.
      nullable: true
    brand_id:
      type: string
      description: The ID of the brand this customer belongs to
      format: uuid
    site_id:
      type: string
      description: |
        Identifier of the site the customer was created at. Customer
        records are scoped per site so each location's CRM data is
        isolated; cross-site reporting is available via the brand or
        organisation.
      format: uuid
    stripe_id:
      type: string
      description: The Stripe Customer ID for this customer
      example: cus_1234567890
      nullable: true
    express_stripe_id:
      type: string
      description: The Stripe Customer ID for this customer if they also exist in Trybe's legacy Stripe integration
      example: cus_1234567890
      nullable: true
    schemas_CustomerLabel:
      type: object
      title: CustomerLabel
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the label
        value:
          type: string
          description: The name of the label
          example: VIP
        colour:
          type: string
          description: A hex colour code excluding the preceding \# which this label will be rendered as.
          example: ff6634
      required:
        - id
        - colour
        - value
    preferred_locale:
      type: string
      description: |
        The preferred locale of the customer.

        This must be one of the platform's supported locales, which can be retrieved using the [`listMetaSupportedLocales`](/endpoints/Meta#listMetaSupportedLocales) endpoint.
      example: en
    locked_at:
      type: string
      format: date-time
      description: |
        The datetime which the customer was locked, or null if it has not been locked.
      nullable: true
    created_at:
      type: string
      format: date-time
      description: The datetime which the customer was created
    updated_at:
      type: string
      format: date-time
      description: The datetime which the customer was last updated
    deleted_at:
      type: string
      format: date-time
      description: The datetime which the customer was anonymised, or null if it has not been.
      nullable: true
    last_active_at:
      type: string
      format: date-time
      description: The datetime which the customer was last active
      nullable: true
    email_verified_at:
      type: string
      format: date-time
      description: The datetime which the customer verified their email address
      nullable: true
    LastCheckInSummary:
      additionalProperties: false
      title: LastCheckInSummary
      type: object
      properties:
        checked_in_at:
          type: string
          format: date-time
          nullable: true
          description: The datetime which the customer was last checked in.
        method:
          type: string
          description: The name of the method used to create this check-in
          example: Scanned
      required:
        - checked_in_at
        - method
    avatar_id:
      type: string
      format: uuid
      description: The media ID of the customer's avatar, or `null` if one hasn't been provided.
      nullable: true
      example: 000000-000000-000000-000000
    external_ref:
      type: string
      description: An external reference for this customer.
      nullable: true
      example: ext-cust-789012
    Customer:
      type: object
      title: Customer
      description: A guest record — the long-lived profile that bookings, orders, payments, memberships and marketing preferences attach to. Customers are scoped to a site (and, where configured, an organisation) and may have multiple addresses, payment methods and external IDs. Their email is the natural login identifier when self-service is enabled.
      additionalProperties: false
      properties:
        id:
          $ref: '#/components/schemas/id'
        first_name:
          $ref: '#/components/schemas/first_name'
        last_name:
          $ref: '#/components/schemas/last_name'
        full_name:
          $ref: '#/components/schemas/full_name'
        phone:
          $ref: '#/components/schemas/phone'
        has_password:
          $ref: '#/components/schemas/has_password'
        dob:
          $ref: '#/components/schemas/dob'
        brand_id:
          $ref: '#/components/schemas/brand_id'
        site_id:
          $ref: '#/components/schemas/site_id'
        stripe_id:
          $ref: '#/components/schemas/stripe_id'
        express_stripe_id:
          $ref: '#/components/schemas/express_stripe_id'
        email:
          $ref: '#/components/schemas/email'
        labels:
          type: array
          description: An array of labels associated with this customer
          items:
            $ref: '#/components/schemas/schemas_CustomerLabel'
        preferred_locale:
          $ref: '#/components/schemas/preferred_locale'
        locked_at:
          $ref: '#/components/schemas/locked_at'
        created_at:
          $ref: '#/components/schemas/created_at'
        updated_at:
          $ref: '#/components/schemas/updated_at'
        deleted_at:
          $ref: '#/components/schemas/deleted_at'
        last_active_at:
          $ref: '#/components/schemas/last_active_at'
        email_verified_at:
          $ref: '#/components/schemas/email_verified_at'
        last_check_in:
          type: object
          description: A summary of the last check-in event associated with this customer, or `null` if they have never checked-in.
          nullable: true
          $ref: '#/components/schemas/LastCheckInSummary'
        avatar_id:
          $ref: '#/components/schemas/avatar_id'
        avatar:
          $ref: '#/components/schemas/Media'
          description: The media object of the customer's avatar, or `null` if one hasn't been provided.
          nullable: true
        external_ref:
          $ref: '#/components/schemas/external_ref'
      required:
        - id
        - first_name
        - last_name
        - full_name
        - phone
        - has_password
        - dob
        - brand_id
        - site_id
        - stripe_id
        - express_stripe_id
        - email
        - labels
        - preferred_locale
        - locked_at
        - created_at
        - updated_at
        - deleted_at
        - last_active_at
        - email_verified_at
        - last_check_in
        - avatar_id
        - avatar
        - external_ref
    password:
      type: string
      format: password
      description: The customer's password. This must be at least 8 characters long
      example: password
    guestline_ref:
      type: string
      description: The guestline reference for this customer.
      example: GL-987654
    BookingItem:
      title: OrderBookingItem
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        added_by_customer:
          type: boolean
        base_price:
          type: integer
        booking_reserved_until:
          type: string
          format: date-time
        booking_summary:
          $ref: '#/components/schemas/BookingSummary'
        date:
          type: string
          format: date
          nullable: true
        discount_amount:
          type: integer
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        exclusive_tax_amount:
          type: integer
        guest:
          $ref: '#/components/schemas/Guest'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        inclusive_tax_amount:
          type: integer
        is_modifiable:
          type: boolean
        item_type:
          type: string
          enum:
            - appointment
            - area_booking
            - session
            - table_reservation
          nullable: true
        net_total:
          type: integer
        order_discount_amount:
          type: integer
        price:
          type: integer
          nullable: true
        sold_by:
          $ref: '#/components/schemas/SoldBy'
        status:
          type: string
          enum:
            - cancelled
            - confirmed
            - pending_confirmation
            - reserved
            - waitlisted
        total_cost:
          type: integer
        type_id:
          type: string
          format: object-id
          nullable: true
        type_name:
          type: string
          nullable: true
        type_product_code:
          type: string
          nullable: true
        warnings:
          type: array
          nullable: true
          description: A list of warnings relating to this item, e.g. missing or mismatched practitioner/room assignments.
          items:
            $ref: '#/components/schemas/OrderItemWarning'
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - added_by_customer
        - booking_summary
        - date
        - discount_amount
        - discounts
        - exclusive_tax_amount
        - guests
        - inclusive_tax_amount
        - is_modifiable
        - item_type
        - net_total
        - order_discount_amount
        - price
        - sold_by
        - status
        - total_cost
        - type_id
        - type_name
        - type_product_code
        - warnings
        - created_at
        - updated_at
    CouponSummary:
      title: CouponSummary
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the coupon.
          type: string
          format: object-id
        code:
          description: The code of the coupon.
          type: string
          example: FIVEOFF
        customer_credit_id:
          description: The customer credit this coupon relates to, if applicable.
          type: string
          format: uuid
        description:
          description: A description of the coupon.
          type: string
          example: Get 10% off all treatments booked in April.
        issued_by_id:
          description: The ID of the entity that issued the coupon.
          type: string
          format: object-id
        issued_by_type:
          description: The type of entity that issued the coupon.
          type: string
          example: credit
        name:
          description: The name of the coupon.
          type: string
          example: April special
      required:
        - id
        - code
        - description
        - name
    CustomerTaxDetails:
      type: object
      title: CustomerTaxDetails
      additionalProperties: false
      properties:
        legal_name:
          type: string
          description: The customer's legal name for tax purposes.
          example: Jane Jones
        tax_id:
          type: string
          description: The customer's tax ID, dependent on their country of residence.
          example: GB1234567
        address_line_1:
          type: string
          description: The first line of the customer's registered address for tax purposes.
          example: 1 Davey Street
        address_line_2:
          type: string
          description: The second line of the customer's registered address for tax purposes.
          example: Clapham
        city:
          type: string
          description: The city of the customer's registered address for tax purposes.
          example: London
        postcode:
          type: string
          description: The postcode of the customer's registered address for tax purposes.
          example: SW4 1AA
        country:
          type: string
          description: The customer's country for tax purposes.
          example: United Kingdom
    ExternalIdValue:
      type: object
      title: ExternalIdValue
      additionalProperties: false
      properties:
        key:
          description: The key for the external ID.
          type: string
          example: pms_id
        name:
          description: The name of the external ID.
          type: string
          example: PMS ID
        value:
          description: The value of the external ID for this order.
          type: string
          example: pms_1234
      required:
        - key
        - name
        - value
    PurchasableDetails:
      title: PurchasableDetails
      description: |
        Details of the item purchased by an `OrderItem` that is a 'purchasable' type. In the
        same way that a 'bookable' order item creates a booking, a 'purchaseable' order item
        creates a purchase object.
      oneOf:
        - title: PurchasableDetailsAppointmentType
          type: object
          additionalProperties: false
          properties:
            id:
              description: The ID of the purchase object.
              type: string
              format: object-id
            time_from:
              description: The start of the range of time being enquired about.
              type: string
              format: date-time
            time_to:
              description: The end of the range of time being enquired about.
              type: string
              format: date-time
          required:
            - id
            - time_from
            - time_to
        - title: PurchasableDetailsVoucherType
          type: object
          additionalProperties: false
          properties:
            id:
              description: The ID of the purchase object.
              type: string
              format: object-id
            email_sent_at:
              description: When the recipient email was sent.
              type: string
              format: date-time
            valid_to_date:
              description: The date the voucher is valid until.
              type: string
              format: date
              nullable: true
          required:
            - id
            - email_sent_at
            - valid_to_date
    schemas_Item:
      title: OrderItem
      description: Any item within an order. This schema replaces the more specific `BookingOrderItem` and `PurchaseOrderItem` schemas.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the item.
          type: string
          format: object-id
        added_by_customer:
          description: Whether this item was added to the basket by the customer.
          type: boolean
        base_price:
          description: If the price has been modified, this value contains the original unit price.
          type: integer
          example: 595
        basket_id:
          type: string
          format: object-id
        booking_summary:
          $ref: '#/components/schemas/BookingSummary'
        discount_amount:
          description: The amount of discount applied to this order item (already deducted from its price and total cost).
          type: integer
          example: 595
        discounts:
          description: An array of discounts applied to the item.
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        exclusive_tax_amount:
          description: The total amount of tax not included in the price of this item
          type: integer
          example: 0
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        has_posted:
          type: boolean
        inclusive_tax_amount:
          description: The total amount of tax included in the price of this item
          type: integer
          example: 49
        item_configuration:
          $ref: '#/components/schemas/ItemConfiguration'
        last_post_attempt:
          type: string
          format: date-time
          nullable: true
        offering:
          $ref: '#/components/schemas/OfferingSummary'
        option_budgets:
          type: array
          items:
            $ref: '#/components/schemas/OptionBudget'
        order_discount_amount:
          type: integer
        package_items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItemPackageItem'
        posted_at:
          type: string
          format: date-time
          nullable: true
        price:
          description: The total price of a single quantity of this order item.
          type: integer
          nullable: true
          example: 595
        purchasable_details:
          $ref: '#/components/schemas/PurchasableDetails'
        quantity:
          description: The quantity of the item.
          type: integer
          example: 1
        reserved_until:
          description: The date and time the booking is reserved until.
          type: string
          format: date-time
          nullable: true
        sold_by:
          description: The staff member responsible for selling this item.
          $ref: '#/components/schemas/SoldBy'
        status:
          $ref: '#/components/schemas/PurchaseItemStatus'
        total_cost:
          description: The total cost of this order item, i.e. its price multiplied by quantity.
          type: integer
          example: 595
        warnings:
          description: A list of warnings relating to this item, e.g. missing or mismatched practitioner/room assignments.
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/OrderItemWarning'
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - added_by_customer
        - basket_id
        - discount_amount
        - discounts
        - exclusive_tax_amount
        - guests
        - inclusive_tax_amount
        - item_configuration
        - offering
        - order_discount_amount
        - price
        - quantity
        - reserved_until
        - sold_by
        - total_cost
        - warnings
        - created_at
        - updated_at
    OrderPackageItem:
      title: OrderPackageItem
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        added_by_customer:
          type: boolean
        base_price:
          type: integer
        date:
          type: string
          format: date
          nullable: true
        discount_amount:
          type: integer
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        exclusive_tax_amount:
          type: integer
        guest:
          $ref: '#/components/schemas/Guest'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        inclusive_tax_amount:
          type: integer
        integration_booking_engine:
          type: string
          nullable: true
          enum:
            - Guestline
        is_modifiable:
          type: boolean
        item_type:
          type: string
          nullable: true
          enum:
            - package
        net_total:
          type: integer
        option_budgets:
          type: array
          items:
            $ref: '#/components/schemas/OptionBudget'
        order_discount_amount:
          type: integer
        package_items:
          type: array
          items:
            title: OrderPackageItemPackageItem
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
              booking_summary:
                $ref: '#/components/schemas/BookingSummary'
              choice_id:
                type: string
                format: object-id
              duration:
                type: integer
                nullable: true
              guests:
                type: array
                items:
                  $ref: '#/components/schemas/Guest'
              item_configuration:
                $ref: '#/components/schemas/ItemConfiguration'
              offering_id:
                type: string
                format: object-id
              offering_name:
                type: string
              offering_type:
                $ref: '#/components/schemas/OfferingType'
              option_id:
                type: string
                format: object-id
              price_change:
                type: integer
              reserved_until:
                type: string
                format: date-time
              shared_basket_item_id:
                type: string
                format: object-id
              status:
                $ref: '#/components/schemas/Status'
              time:
                type: string
                nullable: true
                example: '14:00'
            required:
              - id
              - choice_id
              - duration
              - item_configuration
              - offering_id
              - offering_name
              - offering_type
              - option_id
              - price_change
              - reserved_until
              - time
        price:
          type: integer
          nullable: true
        sold_by:
          $ref: '#/components/schemas/SoldBy'
        status:
          type: string
          enum:
            - cancelled
            - confirmed
            - pending_confirmation
            - reserved
            - waitlisted
        total_cost:
          type: integer
        type_id:
          type: string
          format: object-id
          nullable: true
        type_name:
          type: string
          nullable: true
        type_product_code:
          type: string
          nullable: true
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - added_by_customer
        - date
        - discount_amount
        - discounts
        - exclusive_tax_amount
        - guests
        - inclusive_tax_amount
        - integration_booking_engine
        - is_modifiable
        - item_type
        - net_total
        - option_budgets
        - order_discount_amount
        - package_items
        - price
        - sold_by
        - status
        - total_cost
        - type_id
        - type_name
        - type_product_code
        - created_at
        - updated_at
    PostingRoom:
      title: PostingRoom
      description: A link between an order and a hotel-PMS room folio so that the order's balance can be "posted to room" rather than settled at checkout. Captures the PMS room number, guest reference and timestamp of the association, plus the integration outcome.
      type: object
      additionalProperties: false
      properties:
        associated_at:
          description: |
            The date and time the posting room was associated to the order.
            If not provided, the current date and time will be used.
          type: string
          format: date-time
          nullable: true
        processor_data:
          description: |
            The name of the room to attach to the [`Order`](/endpoints/Orders).
          type: object
          additionalProperties: true
          nullable: true
          example:
            G#: 2081111
            RN: '9500'
      required:
        - associated_at
        - processor_data
    PurchaseItem:
      title: OrderPurchaseItem
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
        added_by_customer:
          type: boolean
        base_price:
          type: integer
        discount_amount:
          type: integer
        discounts:
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        exclusive_tax_amount:
          type: integer
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        inclusive_tax_amount:
          type: integer
        is_modifiable:
          type: boolean
        item_configuration:
          $ref: '#/components/schemas/ItemConfiguration'
        item_type:
          type: string
          nullable: true
          enum:
            - course
            - hotel_room_reservation
            - membership
            - product
            - voucher
          example: product
        net_total:
          type: integer
        order_discount_amount:
          type: integer
        purchasable_details:
          title: OrderPurchaseItemPurchasableDetails
          type: object
          additionalProperties: true
          properties:
            id:
              type: string
              format: object-id
        quantity:
          type: integer
        reserved_until:
          type: string
          format: date-time
        sold_by:
          $ref: '#/components/schemas/SoldBy'
        status:
          type: string
          enum:
            - cancelled
            - confirmed
            - pending_confirmation
            - reserved
            - waitlisted
        total_cost:
          type: integer
        type_id:
          type: string
          format: object-id
          nullable: true
        type_name:
          type: string
          nullable: true
        type_product_code:
          type: string
          nullable: true
        unit_price:
          type: integer
        created_at:
          $ref: '#/components/schemas/createdAt'
        updated_at:
          $ref: '#/components/schemas/updatedAt'
      required:
        - id
        - added_by_customer
        - discount_amount
        - discounts
        - exclusive_tax_amount
        - guests
        - inclusive_tax_amount
        - is_modifiable
        - item_configuration
        - item_type
        - net_total
        - order_discount_amount
        - purchasable_details
        - quantity
        - sold_by
        - status
        - total_cost
        - type_id
        - type_name
        - type_product_code
        - unit_price
        - created_at
        - updated_at
    schemas_SalesChannel:
      type: object
      title: SalesChannel
      additionalProperties: false
      properties:
        id:
          description: The ID of the sales channel.
          type: string
          format: object-id
        name:
          description: The name of the sales channel.
          type: string
          example: Web
        organisation_id:
          type: string
          format: uuid
      required:
        - id
        - name
        - organisation_id
    ServiceChargeItemAmount:
      type: object
      title: OrderServiceChargeItemAmount
      additionalProperties: false
      properties:
        amount:
          description: The amount of the service charge for the item.
          type: integer
          example: 1000
        item_id:
          description: The ID of the item the service charge is applied to.
          type: string
          format: object-id
        percentage:
          description: The percentage of the service charge for the item.
          type: integer
          example: 10
      required:
        - amount
        - item_id
        - percentage
    ServiceCharge:
      title: OrderServiceCharge
      type: object
      additionalProperties: false
      properties:
        amount:
          description: The amount of the service charge.
          type: integer
          example: 1000
        item_amounts:
          type: array
          items:
            $ref: '#/components/schemas/ServiceChargeItemAmount'
        percentage:
          description: The percentage of the service charge.
          type: integer
          example: 10
      required:
        - amount
        - item_amounts
        - percentage
    TaxAmount:
      title: OrderTaxAmount
      type: object
      additionalProperties: false
      properties:
        amount:
          description: The calculated amount of the tax
          type: integer
          example: 1290
        inclusive:
          description: Whether the tax amount is included in the subtotal
          type: boolean
        name:
          description: The name of the tax rate
          type: string
          example: VAT
        percentage:
          description: The percentage of the tax rate
          type: number
          example: 20
      required:
        - amount
        - inclusive
        - name
        - percentage
    Tip:
      title: OrderTip
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the tip.
          type: string
          format: object-id
        amount:
          description: The amount of the tip, in minor units.
          type: integer
          example: 1050
        declined:
          description: Whether the customer explicitly declined to leave a tip
          type: boolean
        updated_at:
          description: The date and time the tip was last updated.
          type: string
          format: date-time
        can_remove:
          description: Whether the tip can be removed from the order.
          type: boolean
      required:
        - id
        - amount
        - declined
        - updated_at
        - can_remove
    schemas_Totals:
      title: OrderTotals
      type: object
      additionalProperties: false
      properties:
        exclusive_tax:
          description: The total amount of exclusive tax included in the subtotal
          type: integer
          example: 0
        inclusive_tax:
          description: The total amount of inclusive tax included in the subtotal
          type: integer
          example: 250
        order_discount:
          description: The total amount of order-level discounts.
          type: integer
          example: 11000
        subtotal:
          description: The amount of the order before discounts, tip and service charge.
          type: integer
          example: 12000
        subtotal_without_exclusive_tax:
          description: The amount of the order before discounts, tip and service charge, excluding any exclusive tax.
          type: integer
          example: 12000
        total:
          description: The total amount of the order.
          type: integer
          example: 10000
      required:
        - exclusive_tax
        - inclusive_tax
        - order_discount
        - subtotal
        - total
    VisitTypeSummary:
      type: object
      title: VisitTypeSummary
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the visit type.
        name:
          type: string
          description: The name of the visit type.
          example: Stay
      required:
        - id
        - name
    OrderVisitSummary:
      type: object
      title: OrderVisitSummary
      additionalProperties: false
      properties:
        id:
          description: The ID of the visit.
          type: string
          format: object-id
        visit_ref:
          description: The reference of the visit.
          type: string
        visit_type:
          $ref: '#/components/schemas/VisitTypeSummary'
        status:
          description: The status of the visit.
          type: string
        arrival_date:
          description: The arrival date of the visit.
          type: string
          format: date-time
        departure_date:
          description: The departure date of the visit.
          type: string
          format: date-time
        first_name:
          description: The first name of the visitor.
          type: string
        last_name:
          description: The last name of the visitor.
          type: string
      required:
        - id
        - visit_ref
        - visit_type
        - status
        - arrival_date
        - departure_date
        - first_name
        - last_name
    OrderV2:
      title: Order
      description: |
        A customer order containing items and payments.
        This format replaces an older version of the order schema, and must be requested
        explicitly by passing `generic_items_array=true` as a query parameter.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the order.
          type: string
          format: object-id
        applied_promo_code:
          description: The summary of the promo code applied to an order.
          $ref: '#/components/schemas/AppliedPromoCode'
        applied_promo_code_discount_total:
          type: integer
        applied_promo_code_id:
          type: string
          format: object-id
          nullable: true
        booking_items:
          type: array
          items:
            $ref: '#/components/schemas/BookingItem'
        booking_items_end_date:
          type: string
          format: date
          nullable: true
        booking_items_start_date:
          type: string
          format: date
          nullable: true
        booking_items_span_multiple_days:
          type: boolean
        coupon_codes:
          description: An array of coupon codes applied to the order.
          type: array
          items:
            $ref: '#/components/schemas/CouponSummary'
        currency:
          $ref: '#/components/schemas/properties_currency'
        customer_id:
          description: The ID of the customer the order belongs to.
          type: string
          nullable: true
          format: uuid
        customer_tax_details:
          $ref: '#/components/schemas/CustomerTaxDetails'
        discount_total:
          description: The total value of all applied order-level discounts.
          type: integer
          example: 100
        discounts:
          description: A list of all applied order-level discounts.
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        email:
          description: The email address of the customer.
          type: string
          nullable: true
          example: janedoe@example.com
        external_ids:
          description: An array of external IDs applied to the order.
          type: array
          items:
            $ref: '#/components/schemas/ExternalIdValue'
        external_ref:
          description: An external reference for the order, if set.
          type: string
          nullable: true
          example: ABC-123
        external_visit_ref:
          description: An external visit reference for the order, if set.
          type: string
          nullable: true
          example: RES1234
        first_name:
          description: The first name of the customer.
          type: string
          nullable: true
          example: Jane
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        intake_form_required:
          description: True if an intake form is required for this order.
          type: boolean
          example: true
        intake_form_url:
          description: The url for the intake form for this order. Only returned on show and submission.
          nullable: true
          type: string
          example: https://demo.try.be/intake-form
        intake_forms_complete:
          description: Whether all intake forms for the order have been completed.
          type: boolean
          example: true
        integration_config_id:
          description: The ID of the integration config associated with this order.
          type: string
          example: 5f344d756e7f2e7d3f2e4b82
        is_customer_required:
          description: True if a customer needs to be set for this order.
          type: boolean
          example: true
        is_locked:
          description: Whether the order is locked.
          type: boolean
          example: false
        is_promo_code_discount_applied:
          type: boolean
        items:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Item'
        items_status:
          description: A summary of the confirmation status of items within the order.
          type: string
          example: confirmed
          enum:
            - confirmed
            - pending_confirmation
        labels:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Label'
        last_name:
          description: The last name of the customer.
          type: string
          nullable: true
          example: Doe
        locked_at:
          description: The date the order was locked at.
          type: string
          format: date-time
          nullable: true
          example: '2019-01-15T12:00:00+01:00'
        net_total:
          description: The net total of all items in the order.
          type: integer
          example: 8000
        order_ref:
          description: The order reference associated with this booking.
          type: string
          nullable: true
          example: TRY00
        organisation_id:
          description: The ID of the organisation the order belongs to.
          type: string
          format: uuid
        outstanding_payment_amount:
          type: integer
        package_items:
          type: array
          items:
            $ref: '#/components/schemas/OrderPackageItem'
        payment_totals:
          $ref: '#/components/schemas/PaymentTotals'
        payments:
          description: A list of all payments against this order.
          type: array
          items:
            $ref: '#/components/schemas/Payment'
        phone:
          description: The customer's phone number.
          type: string
          nullable: true
          example: '+447727123456'
        post_to_room_config:
          title: PostingRoom
          $ref: '#/components/schemas/PostingRoom'
        promo_code_applied_at:
          type: string
          format: date-time
        promo_code_applied_by:
          $ref: '#/components/schemas/UserSummary'
        purchase_items:
          type: array
          items:
            $ref: '#/components/schemas/PurchaseItem'
        sales_channel:
          description: The sales channel of this order.
          $ref: '#/components/schemas/schemas_SalesChannel'
        service_charge:
          $ref: '#/components/schemas/ServiceCharge'
        site_id:
          description: The ID of the site the order belongs to.
          type: string
          format: uuid
        special_requests:
          description: Any customer requests relating to the order.
          type: string
          nullable: true
          example: I would like the Blue Room please
        stage:
          description: The current stage of the order.
          type: string
          nullable: true
          enum:
            - not_arrived
            - arrived
            - in_treatment
            - checked_out
        status:
          $ref: '#/components/schemas/Status'
        submit_auth_amount:
          type: integer
          nullable: true
        submit_payment_amount:
          type: integer
          nullable: true
        submitted_at:
          description: The time and date that the basket was submitted (confirmed).
          type: string
          format: date-time
          nullable: true
          example: '2020-02-24T12:00:00+01:00'
        submitted_by:
          description: Details of the user who submitted the order, if applicable.
          $ref: '#/components/schemas/UserSummary'
        taxes:
          type: array
          items:
            $ref: '#/components/schemas/TaxAmount'
        tip_amount:
          description: The total amount of tip against the order.
          type: integer
          example: 1050
        tips:
          description: An array of individual tips applied to the order.
          type: array
          items:
            $ref: '#/components/schemas/Tip'
        total_cost:
          type: integer
        total_paid_or_authed:
          type: integer
        total_tax:
          description: The total tax amount of all items in the order.
          type: integer
          example: 2000
        totals:
          $ref: '#/components/schemas/schemas_Totals'
        visit:
          $ref: '#/components/schemas/OrderVisitSummary'
        voucher_codes:
          description: An array of discount-type voucher codes applied to the basket. Monetary vouchers are included as payments.
          type: array
          items:
            $ref: '#/components/schemas/VoucherSummary'
        created_at:
          description: The time and date that the basket was created.
          type: string
          format: date-time
          example: '2020-02-24T12:00:00+01:00'
        updated_at:
          description: The time and date that the basket was last updated.
          type: string
          format: date-time
          example: '2020-02-24T12:00:00+01:00'
      required:
        - id
        - applied_promo_code_id
        - booking_items_end_date
        - booking_items_start_date
        - coupon_codes
        - currency
        - customer_id
        - discount_total
        - discounts
        - email
        - first_name
        - guests
        - is_customer_required
        - is_locked
        - items_status
        - labels
        - last_name
        - net_total
        - order_ref
        - organisation_id
        - outstanding_payment_amount
        - payment_totals
        - payments
        - phone
        - sales_channel
        - service_charge
        - site_id
        - special_requests
        - status
        - submit_auth_amount
        - submit_payment_amount
        - taxes
        - tip_amount
        - tips
        - total_cost
        - total_paid_or_authed
        - total_tax
        - totals
        - visit
        - created_at
        - submitted_at
        - updated_at
    PaymentMethod:
      title: PaymentMethod
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the payment method
        payment_method_id:
          type: string
          description: The processor's ID for the payment method
          example: pm_3K6a0RGysTOePye00nkob5Pi
        name:
          type: string
          description: The name of the payment method
          example: My debit card
        type:
          type: string
          enum:
            - card
            - direct_debit
          description: The type of payment method
        status:
          type: string
          description: When the payment method is a Direct Debit mandate, the status shows whether the mandate is usable or not
          example: revoked
        cardholder_name:
          type: string
          description: The cardholder name, or for direct debits, the name of the account holder
          example: Jane Doe
        card_brand:
          type: string
          description: The brand of the card
          example: amex
        card_country:
          type: string
          description: The country where the card was issued
          example: gb
        card_funding:
          type: string
          description: The type of funding for this card
          example: credit
        card_expiry:
          type: string
          description: The expiry month and year for this card
          example: 08/22
        last_4:
          type: string
          description: The last 4 digits of the long card number, or for direct debits, the last 4 digits of the account number
          example: '1234'
        processor:
          type: string
          description: The ID of processor where this payment method is stored
          example: stripe
        created_at:
          type: string
          format: date-time
          description: The datetime which the payment method was created
          example: '2025-01-01T00:00:00+00:00'
        updated_at:
          type: string
          format: date-time
          description: The datetime which the payment method was last updated
          example: '2025-01-01T00:00:00+00:00'
        revoked_at:
          type: string
          format: date-time
          description: The datetime which the payment method was revoked
          example: '2025-01-01T00:00:00+00:00'
      required:
        - id
        - payment_method_id
        - name
        - type
        - status
        - cardholder_name
        - card_brand
        - card_country
        - card_funding
        - card_expiry
        - last_4
        - processor
        - created_at
        - updated_at
    AssociatedBarcode:
      title: AssociatedBarcode
      type: object
      additionalProperties: false
      required:
        - barcode
        - brand_id
        - created_at
        - customer_id
        - customer
        - expires_at
        - id
        - order
        - organisation_id
        - payment_method
        - site_id
        - source
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the associated barcode
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer this barcode is associated with
        customer:
          type: object
          description: The customer this barcode is associated with
          $ref: '#/components/schemas/Customer'
        barcode:
          type: string
          description: The payload of the associated barcode
        expires_at:
          type: string
          format: date-time
          description: The expiry date for the wearable device.
          nullable: true
        brand_id:
          type: string
          format: uuid
          description: The ID of the brand this barcode is associated with
        site_id:
          type: string
          format: uuid
          description: The ID of the site this barcode is associated with
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this barcode is associated with
        source:
          type: string
          description: The source of the associated barcode
          example: kiosk
        order:
          type: object
          description: The ID of the order this barcode is associated with
          $ref: '#/components/schemas/OrderV2'
          nullable: true
        payment_method:
          type: object
          description: The payment method associated with this barcode
          $ref: '#/components/schemas/PaymentMethod'
          nullable: true
        created_at:
          type: string
          format: date-time
          description: The date-time when the barcode was associated
    MemberSummary:
      type: object
      title: MemberSummary
      additionalProperties: false
      properties:
        customer_id:
          description: The ID of the customer
          type: string
          format: uuid
        is_lead:
          description: Whether this member is the lead member
          type: boolean
        membership_number:
          description: The unique membership number of the member
          type: string
          example: '1234567890'
      required:
        - customer_id
        - is_lead
        - membership_number
    MembershipChargeSummary:
      title: ChargeSummary
      description: A summary of a membership charge
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the membership charge
          format: uuid
        amount:
          type: integer
          description: The amount of the charge, in minor units
          example: 3995
        currency:
          type: string
          description: The currency of the charge. See [Supported Currencies](/endpoints/Meta#listMetaSupportedCurrencies) for a list of supported currencies.
          example: GBP
        status:
          type: string
          description: The status of the charge.
          enum:
            - awaiting_approval
            - pending
            - succeeded
            - processing
            - errored
            - failed
        billing_period_from:
          type: string
          format: date
          description: The first date covered by the charge
        billing_period_to:
          type: string
          format: date
          description: The last date covered by the charge
      required:
        - id
        - amount
        - currency
        - status
        - billing_period_from
        - billing_period_to
    MembershipRate:
      title: MembershipRate
      type: object
      additionalProperties: false
      required:
        - id
        - billing_frequency
        - created_at
        - currency
        - default_duration
        - joining_fee
        - membership_type_id
        - name
        - notice_period
        - price
        - processors
        - private
        - updated_at
      properties:
        id:
          type: string
          description: The ID of the membership rate
          format: uuid
        membership_type_id:
          type: string
          description: The ID of the `MembershipType` which this rate belongs to
          format: uuid
        name:
          type: string
          description: The name of the membership rate
          example: Standard rate
        currency:
          type: string
          description: The currency which all monetary values of this rate are in, uppercase, in the ISO4217 format
          example: GBP
        price:
          type: number
          description: The price of the rate as an integer of the smallest unit eg pence. This is charged to the customer every billing period according to the `billing_frequency`
          example: 5000
        joining_fee:
          type: number
          description: The price of the joining fee as an integer of the smallest unit eg pence.
          example: 1000
        billing_frequency:
          type: string
          description: |
            The frequency that this membership is billed.
            The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1M
        processors:
          type: array
          items:
            type: string
        default_duration:
          type: string
          nullable: true
          description: |
            The default duration of the membership. This is used when a customer signs themselves up for a membership.
            The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1Y
        notice_period:
          type: string
          nullable: true
          enum:
            - P7D
            - P14D
            - P1M
            - P3M
            - P6M
            - P1Y
            - null
          description: |
            How much notice a customer must give to cancel a membership on this rate.
            The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            When null, no notice is required.
          example: P1M
        private:
          type: boolean
          description: |
            Whether this `MembershipRate` is private. If public, it will be selectable on the self-signup flow.
          example: true
        created_at:
          type: string
          format: date-time
          description: The datetime which the rate was created
        updated_at:
          type: string
          format: date-time
          description: The datetime which the membership was last updated
    MembershipType:
      type: object
      title: MembershipType
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the membership type
          format: uuid
        name:
          type: string
          description: The name of the membership type
          example: Gold tier
        description:
          type: string
          description: The description of the membership type
          example: Enjoy exclusive benefits as part of being a member in our Gold tier
          nullable: true
        terms:
          type: string
          description: Terms and conditions of the membership type
          nullable: true
        brand_id:
          type: string
          description: The ID of the brand this type is linked to
          format: uuid
        offline_payments:
          type: boolean
          description: |
            Whether this MembershipType takes "offline" payments. If true, the monthly fee won't automatically be collected
            using Stripe, which can be useful if a different provider is used for collecting direct debits. You'll need to
            manually manage the membership status.
        disable_confirmation_email:
          type: boolean
          description: |
            Whether to disable sending the confirmation email when a membership is confirmed.
        private:
          type: boolean
          deprecated: true
          description: |
            Whether this `MembershipType` is private or not.

            When a `MembershipType` is private, it won't be shown to users on the site's shop frontend.

            This field is deprecated and has been superceded by `visibility`.
        visibility:
          type: string
          description: |
            The visibility of the `MembershipType` on the site's shop frontend.
          enum:
            - public
            - private
            - link_only
        minimum_start_date:
          type: string
          format: date-time
          description: The minimum start date for a membership of this type.
          nullable: true
        min_members:
          type: integer
          description: The minimum number of members required to create a membership of this type
          example: 2
        max_members:
          type: integer
          description: The maximum number of members allowed to create a membership of this type
          example: 4
        rates:
          description: The public MembershipRates for this type, or if a `MembershipSignupToken` was passed, the rate linked to that.
          type: array
          items:
            $ref: '#/components/schemas/MembershipRate'
        revenue_schedule:
          description: The schedule that revenues for this membership should be created, as an [RRULE](https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html) string
          type: string
          example: FREQ=WEEKLY
          nullable: true
        created_at:
          type: string
          format: date-time
          description: The datetime which the membership type was created
        updated_at:
          type: string
          format: date-time
          description: The datetime which the membership type was last updated
        deleted_at:
          type: string
          format: date-time
          description: The datetime which the membership type was archived, or null if it isn't archived.
          nullable: true
      required:
        - id
        - name
        - description
        - terms
        - brand_id
        - offline_payments
        - disable_confirmation_email
        - private
        - minimum_start_date
        - min_members
        - max_members
        - rates
        - revenue_schedule
        - created_at
        - updated_at
        - deleted_at
    Membership:
      title: Membership
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the membership
          type: string
          format: uuid
        attention_reason:
          description: A string describing what kind of action needs to take place
          type: string
          enum:
            - no_mandate
            - setup_unpaid
            - mandate_revoked
            - payment_failed
            - payment_disputed
            - payment_outstanding
            - site_id
        basket_id:
          description: The basket ID which was used to purchase this membership, if applicable.
          type: string
          format: mongo-id
        customer:
          type: object
          $ref: '#/components/schemas/Customer'
        end_date:
          description: The date which the membership ends
          type: string
          format: date-time
          nullable: true
        external_ref:
          description: An external reference for this membership.
          type: string
        members:
          type: array
          items:
            $ref: '#/components/schemas/MemberSummary'
        membership_number:
          description: |
            The unique membership number of the lead member. This is always a 10 digit numeric string.
            Since this field only relates to the lead member, this is now deprecated.
            Instead, find the membership for the relevant customer in the `members` array.
          type: string
          example: '1234567890'
          deprecated: true
        next_billing_date:
          description: The date which the membership will next be billed
          type: string
          format: date-time
          nullable: true
        next_charge:
          description: |
            A summary of the next charge that's due for this membership.

            This property is only populated when the membership was retrieved using the `[getCustomerMemberships](/endpoints/Customers#getCustomerMemberships) endpoint.
          type: object
          $ref: '#/components/schemas/MembershipChargeSummary'
          nullable: true
        payment_method:
          title: PaymentMethod
          description: |
            Details about the payment method attached to this membership. This payment method
            is used to take payment on the monthly billing period. If a payment method hasn't
            been set up, this will be null.
          type: object
          nullable: true
          additionalProperties: false
          properties:
            id:
              description: The ID of the payment method this membership uses for
              type: string
            type:
              description: The type of payment method.
              type: string
              enum:
                - card
                - direct_debit
            last_4:
              description: The last 4 digits of the long card number or the bank account number.
              type: string
            status:
              description: When the payment method is a Direct Debit mandate, the status shows whether the mandate is usable or not
              type: string
              example: revoked
            card_brand:
              description: The brand of the card
              type: string
              example: amex
        rate:
          type: object
          $ref: '#/components/schemas/MembershipRate'
        site_id:
          description: The ID of the site this membership belongs to
          type: string
          format: uuid
        source:
          description: Where the membership was created
          type: string
          enum:
            - self_signup
            - app
            - import
            - unknown
        start_date:
          description: The date which the membership starts
          type: string
          format: date-time
        status:
          type: string
          enum:
            - active
            - needs_dd_mandate
            - needs_attention
            - reserved
            - inactive
            - expired
            - upcoming
        status_updated_at:
          type: string
          format: date-time
        type:
          type: object
          $ref: '#/components/schemas/MembershipType'
        payment_details_url:
          type: string
          description: A URL to a page where the member can provide their payment details.
        created_at:
          description: The datetime which the membership was created
          type: string
          format: date-time
      required:
        - id
        - attention_reason
        - basket_id
        - end_date
        - external_ref
        - members
        - membership_number
        - next_billing_date
        - payment_method
        - rate
        - site_id
        - source
        - start_date
        - status
        - status_updated_at
        - type
        - created_at
    MarketingPreference:
      title: MarketingPreference
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the marketing preference
        text:
          type: string
          description: The text of the marketing preference
          example: I want to receive emails about special offers
        locale:
          type: string
          description: |
            The locale this marketing preference's text is written in. A marketing
            preference only ever has one language; to offer the same preference in
            multiple languages, create a separate marketing preference per locale.

            This must be one of the platform's supported locales, which can be retrieved using the [`listMetaSupportedLocales`](/endpoints/Meta#listMetaSupportedLocales) endpoint.
          example: en
        organisation_id:
          type: string
          description: The ID of the organisation this marketing preference is linked to
        created_at:
          type: string
          format: date-time
          description: The date and time which the marketing preference was created
        updated_at:
          type: string
          format: date-time
          description: The date and time which the marketing preference was last updated
      required:
        - id
        - text
        - locale
        - organisation_id
        - created_at
        - updated_at
    InventoryBrand:
      title: InventoryBrand
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory brand.
        name:
          type: string
          description: The name of the inventory brand.
          example: L'Oréal
        site_id:
          type: string
          format: uuid
          description: The ID of the site the inventory brand belongs to.
          nullable: true
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the inventory brand belongs to.
      required:
        - id
        - name
        - site_id
        - organisation_id
    InventoryCategory:
      title: InventoryCategory
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory category.
        name:
          type: string
          description: The name of the inventory category.
          example: Massage oils
        site_id:
          type: string
          format: uuid
          description: The ID of the site the inventory category belongs to.
          nullable: true
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the inventory category belongs to.
        order:
          type: integer
          description: |
            The display order of the inventory category within its site. Lower
            values are shown first. Set via the reorder endpoint.
          example: 0
      required:
        - id
        - name
        - site_id
        - organisation_id
        - order
    Supplier:
      title: Supplier
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the supplier.
        name:
          type: string
          description: The name of the supplier.
          example: Elemis
        email:
          type: string
          description: An email address for the supplier.
          example: orders@example.com
          nullable: true
        phone:
          type: string
          description: A phone number for the supplier.
          example: +44 20 8012 3456
          nullable: true
        address_1:
          type: string
          description: The first line of the supplier's address.
          example: Unit E, Dominion Way
          nullable: true
        address_2:
          type: string
          description: The second line of the supplier's address.
          example: Rustington
          nullable: true
        city:
          type: string
          description: The city part of the supplier's address.
          example: Littlehampton
          nullable: true
        county:
          type: string
          description: The county part of the supplier's address.
          example: West Sussex
          nullable: true
        country:
          type: string
          description: The country part of the supplier's address.
          example: UK
          nullable: true
        postcode:
          type: string
          description: The ZIP or postal code part of the supplier's address.
          example: BN16 3HQ
          nullable: true
        site_id:
          type: string
          format: uuid
          description: The ID of the site this supplier record belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this supplier record belongs to.
      required:
        - id
        - name
        - email
        - phone
        - address_1
        - address_2
        - city
        - county
        - country
        - postcode
        - site_id
        - organisation_id
    SupplierProduct:
      title: SupplierProduct
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the product-supplier relationship.
        product_id:
          type: string
          format: uuid
          description: The ID of the product.
        product_name:
          type: string
          description: The name of the product.
          example: Blissful Body Butter
        supplier_id:
          type: string
          format: uuid
          description: The ID of the supplier.
        supplier_name:
          type: string
          description: The name of the supplier.
          example: Elemis
        supplier_product_id:
          type: string
          format: uuid
          description: The ID of the supplier product.
        order_quantity:
          type: integer
          description: The default quantity of the product to order from this supplier.
          example: 10
        unit_price:
          type: integer
          description: The unit price of this item in the lowest denomination for the product's currency.
          example: 200
        currency:
          type: string
          description: The currency of the product.
          example: gbp
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this product-supplier record belongs to.
      required:
        - id
        - product_id
        - supplier_id
        - supplier_product_id
        - order_quantity
        - unit_price
        - currency
        - organisation_id
    InventoryProduct:
      title: InventoryProduct
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory product.
        name:
          type: string
          description: The name of the inventory product.
          example: Blissful Body Butter
        description:
          type: string
          description: A description of the inventory product.
          example: A rich, creamy body butter which deeply nourishes the skin, with essential oils.
          nullable: true
        sku:
          type: string
          description: A stock keeping unit (SKU) for the inventory product.
          example: BB-001
          nullable: true
        barcode:
          type: string
          description: A barcode for the inventory product.
          example: 123456789
          nullable: true
        average_cost:
          type: integer
          description: The average cost of the inventory product in the lowest denomination for this product's currency.
          example: 1000
        currency:
          type: string
          description: The currency of the inventory product.
          example: gbp
        reorder_level:
          type: integer
          description: The quantity of this inventory product which should be reordered.
          example: 10
          nullable: true
        stock_level:
          type: number
          description: The quantity of this stock at the site.
          example: 50.5
        stock_value:
          type: integer
          description: The total value of this stock at the site in the lowest denomination for this product's currency.
          example: 5000
        brand_id:
          type: string
          format: uuid
          description: The ID of the brand this inventory product belongs to.
          nullable: true
        brand:
          $ref: '#/components/schemas/InventoryBrand'
          nullable: true
        category_id:
          type: string
          format: uuid
          description: The ID of the category this inventory product belongs to.
          nullable: true
        category:
          $ref: '#/components/schemas/InventoryCategory'
          nullable: true
        site_id:
          type: string
          format: uuid
          description: The ID of the site this inventory product belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this inventory product belongs to.
      required:
        - id
        - name
        - description
        - sku
        - barcode
        - average_cost
        - currency
        - reorder_level
        - stock_level
        - stock_value
        - brand_id
        - category_id
        - site_id
        - organisation_id
    InventoryProductAdjustment:
      title: InventoryProductAdjustment
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory product adjustment.
        quantity:
          type: number
          description: The amount of the adjustment, which may be positive or negative.
          example: 10.5
        reason_code:
          type: string
          description: The preset reason code for the adjustment.
          example: Professional Use
        reason_description:
          type: string
          description: A free-text description of the reason for the adjustment.
          example: Stock used for professional use
        product_id:
          type: string
          format: uuid
          description: The ID of the inventory product this adjustment is for.
        location_id:
          type: string
          format: uuid
          description: The ID of the location the stock is moving from.
        site_id:
          type: string
          format: uuid
          description: The ID of the site this adjustment belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this adjustment belongs to.
        user_id:
          type: string
          format: uuid
          description: The ID of the user who created the adjustment.
          nullable: true
        created_at:
          type: string
          format: date-time
          description: The date and time the adjustment was created.
          example: '2024-05-01T00:00:00Z'
      required:
        - id
        - quantity
        - reason_code
        - reason_description
        - product_id
        - location_id
        - site_id
        - organisation_id
        - user_id
        - created_at
    InventoryProductSupplier:
      title: InventoryProductSupplier
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the product-supplier relationship.
        product_id:
          type: string
          format: uuid
          description: The ID of the inventory product.
        product_name:
          type: string
          description: The name of the inventory product.
          example: Blissful Body Butter
        supplier_id:
          type: string
          format: uuid
          description: The ID of the supplier.
        supplier_name:
          type: string
          description: The name of the supplier.
          example: Elemis
        supplier_product_id:
          type: string
          format: uuid
          description: The ID of the supplier product.
        order_quantity:
          type: integer
          description: The default quantity of the inventory product to be ordered from this supplier.
          example: 10
        unit_price:
          type: integer
          description: The unit price of the inventory product in the lowest denomination for this product's currency.
          example: 200
        currency:
          type: string
          description: The currency of the inventory product.
          example: gbp
        site_id:
          type: string
          format: uuid
          description: The ID of the site this product-supplier record belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this product-supplier record belongs to.
        deleted_at:
          type: string
          format: date-time
          description: The date and time this product-supplier record was deleted.
          nullable: true
      required:
        - id
        - product_id
        - supplier_id
        - supplier_product_id
        - order_quantity
        - unit_price
        - currency
        - site_id
        - organisation_id
        - deleted_at
    InventoryIdEntry:
      type: object
      title: InventoryIdEntry
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID.
        name:
          type: string
          description: The name of the model the inventory ID relates to.
          example: Blissful Body Butter
        type:
          type: string
          description: The type of model the inventory ID represents.
          example: product
    InventoryOrder:
      title: InventoryOrder
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory order.
        status:
          type: string
          description: The status of the inventory order.
          enum:
            - draft
            - submitted
            - received
        purchase_order_number:
          type: string
          description: The purchase order number for this inventory order.
          example: PO123
        supplier_id:
          type: string
          format: uuid
          description: The ID of the supplier for this inventory order.
        supplier_name:
          type: string
          description: The name of the supplier for this inventory order.
          example: Elemis
        supplier_email:
          type: string
          description: An email address for the supplier of this inventory order.
          example: orders@example.com
        subtotal:
          type: integer
          description: The subtotal of the order in the lowest denomination for this order's currency.
          example: 2000
        currency:
          type: string
          description: The currency of the inventory order.
          example: gbp
        item_count:
          type: integer
          description: The total number of items in the inventory order.
          example: 10
        items_added:
          type: boolean
          description: Whether items have been added to the order.
        created_by_id:
          type: string
          format: uuid
          description: The ID of the user who created the inventory order.
          nullable: true
        site_id:
          type: string
          format: uuid
          description: The ID of the site this inventory order belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this inventory order belongs to.
        created_at:
          type: string
          format: date-time
          description: The date and time the inventory order was created.
          example: '2024-06-01T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time the inventory order was last updated.
          example: '2024-06-01T12:00:00Z'
        submitted_at:
          type: string
          format: date-time
          description: The date and time the inventory order was submitted.
          example: '2024-06-01T12:00:00Z'
          nullable: true
        last_submitted_at:
          type: string
          format: date-time
          description: The date and time the inventory order was last submitted.
          example: '2024-06-02T12:00:00Z'
          nullable: true
      required:
        - id
        - status
        - supplier_id
        - supplier_name
        - supplier_email
        - subtotal
        - currency
        - item_count
        - items_added
        - created_by_id
        - site_id
        - organisation_id
        - created_at
        - updated_at
        - submitted_at
        - last_submitted_at
    InventoryOrderItem:
      title: InventoryOrderItem
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory order item.
        order_id:
          type: string
          format: uuid
          description: The ID of the inventory order the item belongs to.
        quantity:
          type: integer
          description: The quantity of the item to be ordered.
          example: 10
        unit_price:
          type: integer
          description: The unit price of the item in the lowest denomination for the product's currency.
          example: 200
        product_id:
          type: string
          format: uuid
          description: The ID of the inventory product to be ordered.
        product_name:
          type: string
          description: The name of the inventory product to be ordered.
          example: Blissful Body Butter
        line_total:
          type: integer
          description: The total price of the item in the lowest denomination for the supplier's currency.
          example: 2000
      required:
        - id
        - order_id
        - quantity
        - unit_price
        - product_id
        - product_name
        - line_total
    InventoryOrderWithItems:
      title: InventoryOrderWithItems
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory order.
        status:
          type: string
          description: The status of the inventory order.
          enum:
            - draft
            - submitted
            - received
        purchase_order_number:
          type: string
          description: The purchase order number for this inventory order.
          example: PO123
        supplier_id:
          type: string
          format: uuid
          description: The ID of the supplier for this inventory order.
        supplier_name:
          type: string
          description: The name of the supplier for this inventory order.
          example: Elemis
        supplier_email:
          type: string
          description: An email address for the supplier of this inventory order.
          example: orders@example.com
        subtotal:
          type: integer
          description: The subtotal of the order in the lowest denomination for this order's currency.
          example: 2000
        currency:
          type: string
          description: The currency of the inventory order.
          example: gbp
        item_count:
          type: integer
          description: The total number of items in the inventory order.
          example: 10
        items:
          type: array
          items:
            $ref: '#/components/schemas/InventoryOrderItem'
        created_by_id:
          type: string
          format: uuid
          description: The ID of the user who created the inventory order.
          nullable: true
        items_added:
          type: boolean
          description: Whether items have been added to the order.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this inventory order belongs to.
        created_at:
          type: string
          format: date-time
          description: The date and time the inventory order was created.
          example: '2024-06-01T12:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time the inventory order was last updated.
          example: '2024-06-01T12:00:00Z'
        submitted_at:
          type: string
          format: date-time
          description: The date and time the inventory order was submitted.
          example: '2024-06-01T12:00:00Z'
          nullable: true
        last_submitted_at:
          type: string
          format: date-time
          description: The date and time the inventory order was last submitted.
          example: '2024-06-02T12:00:00Z'
          nullable: true
      required:
        - id
        - status
        - purchase_order_number
        - supplier_id
        - supplier_name
        - subtotal
        - currency
        - item_count
        - items
        - created_by_id
        - organisation_id
        - created_at
        - updated_at
        - submitted_at
        - last_submitted_at
        - items_added
    schemas_UserSummary:
      title: InventoryUserSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the user
          format: uuid
        email:
          type: string
        first_name:
          type: string
          description: The first name of the user
          example: Dan
        last_name:
          type: string
          description: The last name of the user
          example: Johnson
        full_name:
          type: string
          description: The full name of the user
          example: Dan Johnson
      required:
        - id
        - email
        - first_name
        - last_name
        - full_name
    StockTake:
      title: StockTake
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the stocktake.
        description:
          type: string
          description: The description of the stocktake.
          example: Stocktake started on 01/06/2024
        status:
          type: string
          description: The status of the stocktake.
          enum:
            - in_progress
            - complete
        currency:
          type: string
          description: The currency of the stocktake.
          example: gbp
        created_by_id:
          type: string
          format: uuid
          description: The ID of the user who created the stocktake.
          nullable: true
        created_by:
          type: object
          description: The summary of the user who created the stocktake.
          $ref: '#/components/schemas/schemas_UserSummary'
          nullable: true
        posted_by_id:
          type: string
          format: uuid
          description: The ID of the user who posted the stocktake.
          nullable: true
        posted_by:
          type: object
          description: The summary of the user who posted the stocktake.
          $ref: '#/components/schemas/schemas_UserSummary'
          nullable: true
        items_added:
          type: boolean
          description: Whether items have been added to the stock take.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the stocktake belongs to.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this stocktake belongs to.
        created_at:
          type: string
          format: date-time
          description: The date and time the stocktake was created.
          example: '2024-06-01T12:00:00Z'
        posted_at:
          type: string
          format: date-time
          description: The date and time the stocktake was posted.
          nullable: true
        updated_at:
          type: string
          format: date-time
          description: The date and time the stocktake was last updated.
      required:
        - id
        - description
        - status
        - currency
        - created_by_id
        - items_added
        - site_id
        - organisation_id
        - created_at
        - posted_at
        - updated_at
    StockTakeItem:
      title: StockTakeItem
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the stock take item.
        stock_take_id:
          type: string
          format: uuid
          description: The ID of the stock take this item belongs to.
        product_id:
          type: string
          format: uuid
          description: The ID of the inventory product this stocktake item belongs to.
        name:
          type: string
          description: The name of the inventory product.
          example: Blissful Body Butter
        sku:
          type: string
          description: The stock keeping unit (SKU) for the stocktake item.
          example: BB-001
          nullable: true
        unit_cost:
          type: integer
          description: The unit cost of the stocktake item in the lowest denomination for the product's currency.
          example: 2000
        counted_quantity:
          type: number
          description: The quantity counted for this stocktake item.
          example: 50.5
        expected_quantity:
          type: number
          description: The expected quantity for this stocktake item.
          example: 70.5
        adjusted_quantity:
          type: number
          description: The adjusted quantity for this stocktake item.
          example: 20.5
        adjusted_value:
          type: integer
          description: The adjusted value for this stocktake item.
          example: 70
        created_at:
          type: string
          format: date-time
          description: The date and time the stock take item was created.
          example: '2024-06-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time the stock take item was last updated.
          example: '2024-06-01T00:00:00Z'
      required:
        - id
        - stock_take_id
        - product_id
        - name
        - unit_cost
        - counted_quantity
        - expected_quantity
        - adjusted_quantity
        - adjusted_value
        - created_at
        - updated_at
    StockTakeItemsTotals:
      title: StockTakeItemsTotals
      type: object
      additionalProperties: false
      properties:
        items:
          type: integer
          description: The total number of items in the stock take.
          example: 100
        counted:
          type: integer
          description: The total number of items counted in the stock take.
          example: 50
        uncounted:
          type: integer
          description: The total number of items uncounted in the stock take.
          example: 50
        adjustment_value:
          type: integer
          description: The value of the total adjustments for the stock take.
          example: 1000
    StockOnHand:
      type: object
      title: StockOnHand
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the inventory product.
        name:
          type: string
          description: The name of the inventory product.
          example: Blissful Body Butter
        stock_level:
          type: number
          description: The current stock level of the inventory product.
          example: 100.5
        stock_value:
          type: integer
          description: The current stock value of the inventory product.
          example: 2000
        average_cost:
          type: integer
          description: The average cost of the inventory product.
          example: 2000
    StockOnHandMeta:
      type: object
      title: StockOnHandMeta
      additionalProperties: false
      properties:
        total_stock_value:
          type: integer
          description: The total stock value of all inventory products.
          example: 2000
        currency:
          type: string
          description: The currency of the stock on hand.
          example: gbp
    StockAdjustment:
      type: object
      title: StockAdjustment
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the stock adjustment.
        date:
          type: string
          format: date-time
          description: The date and time of the stock adjustment.
        product_id:
          type: string
          format: uuid
          description: The ID of the inventory product.
        product_name:
          type: string
          description: The name of the inventory product.
          example: Blissful Body Butter
        quantity:
          type: number
          description: The quantity of the stock adjustment.
          example: 10
        reason_code:
          type: string
          description: The reason code for the stock adjustment.
          example: Sale
        reason_description:
          type: string
          description: The reason description for the stock adjustment.
          example: Sale of 10 Blissful Body Butter products
          nullable: true
        adjusted_by_id:
          type: string
          format: uuid
          description: The ID of the user who adjusted the stock.
          nullable: true
        adjusted_by:
          type: object
          description: The summary of the user who adjusted the stock.
          $ref: '#/components/schemas/schemas_UserSummary'
          nullable: true
        adjusted_value:
          type: integer
          description: The value of the stock adjustment.
          example: 2000
        currency:
          type: string
          description: The currency of the stock adjustment.
          example: gbp
    schemas_OrderSummary:
      title: OrderSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the order.
        order_ref:
          type: string
          description: The reference of the order.
          example: TRY00
        full_name:
          type: string
          description: The full name of the customer who placed the order.
          example: Jessica Jones
      required:
        - id
        - order_ref
    AppointmentEnquiry:
      type: object
      title: AppointmentEnquiry
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the appointment enquiry.
        appointment_type_id:
          type: string
          format: object-id
          description: The ID of the appointment the enquiry is for.
        appointment_type_name:
          type: string
          description: The name of the appointment the enquiry is for.
        time_from:
          type: string
          format: date-time
          description: The earliest date and time the appointment could start.
        time_to:
          type: string
          format: date-time
          description: The latest date and time the appointment could start.
        status:
          type: string
          description: The status of the enquiry
          enum:
            - received
            - confirmed
            - cancelled
        can_confirm:
          type: boolean
          description: Whether there is availability for the enquiry to be confirmed as an appointment.
        cancellation_reason:
          type: string
          nullable: true
          description: A reason code for the cancellation, if any.
          example: expired
        order:
          description: Details of the order the enquiry was part of.
          $ref: '#/components/schemas/schemas_OrderSummary'
        last_checked_at:
          type: string
          nullable: true
          format: date-time
          description: The date and time availability was last checked for this enquiry.
        received_at:
          type: string
          format: date-time
          description: The date and time the enquiry was received.
      required:
        - id
        - appointment_type_id
        - appointment_type_name
        - time_from
        - time_to
        - status
        - can_confirm
        - order
        - last_checked_at
        - received_at
    CouponLocaleStrings:
      title: CouponLocaleStrings
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
          description: The localised name for this coupon in the given locale.
          example: Free 30 minute massage
        description:
          type: string
          nullable: true
          description: The localised description for this coupon in the given locale.
          example: Enjoy a free 30 minute massage as a thanks for being a loyal member
      required:
        - name
        - description
    OfferingDiscountItem:
      title: OfferingDiscountItem
      type: object
      additionalProperties: false
      properties:
        offering_type:
          type: string
          enum:
            - appointment
            - package
            - product
            - session
            - area_booking
          description: The type of offering
        offering_id:
          type: string
          format: object-id
          description: The ID of the offering
        offering_name:
          type: string
          description: The name of the offering
          example: Test offering
      required:
        - offering_type
        - offering_id
        - offering_name
    OfferingDiscount:
      title: OfferingDiscount
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: ID of the offering discount
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingDiscountItem'
        discount_type:
          type: string
          enum:
            - fixed_amount
            - percentage
          description: The type of discount to be applied
        fixed_amount:
          type: integer
          description: The amount of discount to apply as an integer of the smallest unit of currency.
          example: 50
        percentage:
          type: integer
          description: The percentage of discount to apply
          example: 10
      required:
        - id
        - offerings
        - discount_type
        - fixed_amount
        - percentage
    Coupon:
      title: Coupon
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the coupon
        name:
          type: string
          description: The name of the coupon
          example: Test coupon
        description:
          type: string
          description: A string to describe the coupon
          example: This coupon is a test
        locale_strings:
          type: object
          nullable: true
          description: Translations of the coupon's name and description, keyed by locale code. Managed via the coupon locale strings endpoints.
          additionalProperties:
            $ref: '#/components/schemas/CouponLocaleStrings'
        offering_discounts:
          type: array
          description: An array of offering_discounts belonging to this coupon. Each offering_discount describes what offerings the coupon is valid for.
          items:
            $ref: '#/components/schemas/OfferingDiscount'
        currency:
          type: string
          description: The currency of any amounts to be applied.
          example: gbp
        valid_weekdays:
          type: array
          description: An array of weekdays which this coupon is available for use
          items:
            type: string
            description: A weekday, in English, lowercase, and not shortened
            example: monday
        invalid_date_set_ids:
          type: array
          description: An array of IDs of `DateSet`s describing when this coupon is _not_ valid. The DateSet must belong to the same organisation as the coupon.
          items:
            type: string
            format: object-id
            description: The ID of the date set
        default_validity_interval:
          type: string
          description: The default duration this coupon is valid for, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1Y
        default_multi_use:
          type: boolean
          description: The default for whether a code created from this coupon may be used multiple times
          example: true
        for_lead_booker_only:
          type: boolean
          description: |
            If true, only the lead booker of an order will be able to use this coupon. If false, any guest on the order will be able to use the coupon, including non-members.
          example: true
        max_uses:
          type: integer
          nullable: true
          description: The maximum number of times this coupon can be used within the specified max uses period
          example: 2
        max_uses_period:
          type: string
          nullable: true
          enum:
            - P1D
            - P1W
            - P1M
            - P1Y
          description: |
            The time period for usage limits when max_uses is set.
            The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
            P1D = daily limit, P1W = weekly limit, P1M = monthly limit, P1Y = yearly limit
        redemption_type:
          type: string
          enum:
            - manual
            - programmatic
          description: The redemption type of the coupon.
          example: manual
        site_id:
          type: string
          format: uuid
          nullable: true
          description: The ID of the site this coupon belongs to.
        created_at:
          type: string
          format: date-time
          description: The time and date that the coupon was created.
          example: '2020-02-24T12:00:00+01:00'
        updated_at:
          type: string
          format: date-time
          description: The time and date that the coupon was last updated.
          example: '2020-02-24T12:00:00+01:00'
        deleted_at:
          type: string
          format: date-time
          description: The time and date that the coupon was soft-deleted.
          example: '2020-02-24T12:00:00+01:00'
          nullable: true
      required:
        - id
        - name
        - description
        - locale_strings
        - offering_discounts
        - currency
        - valid_weekdays
        - invalid_date_set_ids
        - default_validity_interval
        - default_multi_use
        - for_lead_booker_only
        - max_uses
        - max_uses_period
        - redemption_type
        - site_id
        - created_at
        - updated_at
        - deleted_at
    CouponCode:
      title: CouponCode
      description: |
        A `CouponCode` is a redeemable code attached to a `Coupon`. The
        coupon defines the credit-issue rules; the code is what a customer
        types at checkout to claim it. Codes can be single- or multi-use,
        time-limited, and optionally pre-allocated to a specific customer.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for this coupon code.
          example: 5f1234567890abcdef123456
        code:
          type: string
          description: The redemption code customers type at checkout. Auto-generated when not specified on create.
          example: SUMMER2026
        coupon_id:
          type: string
          format: object-id
          description: ID of the parent `Coupon` this code belongs to.
          example: 5f1234567890abcdef123456
        valid_from_date:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO 8601 timestamp from which the code is redeemable. Null =
            valid immediately.
          example: '2026-06-01T00:00:00Z'
        valid_to_date:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO 8601 timestamp after which the code expires. Null = no
            expiry.
          example: '2026-08-31T23:59:59Z'
        multi_use:
          type: boolean
          description: |
            When true, the same code can be redeemed multiple times (once
            per customer). When false, the code is single-use and burns
            after the first redemption.
          example: false
        customer_credit_id:
          type: string
          nullable: true
          description: |
            If set, the code is pre-allocated to a specific
            `CustomerCredit` record — typically used to issue targeted
            promotional credits to a known customer.
          example: 5f1234567890abcdef123456
        customer_id:
          type: string
          format: uuid
          nullable: true
          description: |
            ID of the customer this code is pre-allocated to. Required
            when `customer_credit_id` is set.
          example: 11111111-1111-1111-1111-111111111111
        revenue:
          type: integer
          nullable: true
          description: |
            Override revenue value in the smallest currency unit (e.g.
            pence/cents) for this code's redemption. When null, the
            parent coupon's revenue rules apply.
          example: 5000
      required:
        - id
        - code
        - coupon_id
        - multi_use
    schemas_Offering:
      title: Offering
      type: object
      additionalProperties: false
      properties:
        offering_type:
          type: string
          enum:
            - appointment
            - package
            - product
            - session
            - area_booking
          description: The type of offering
        offering_id:
          type: string
          format: object-id
          description: The ID of the offering
    CouponCodeUsageStats:
      type: object
      title: CouponCodeUsageStats
      additionalProperties: false
      properties:
        max_uses:
          type: integer
          description: The maximum number of times this coupon can be used within the period
          example: 4
        current_uses:
          type: integer
          description: The number of times this coupon has been used in the current period
          example: 2
        remaining_uses:
          type: integer
          description: The number of remaining uses available in the current period
          example: 2
        period:
          type: string
          enum:
            - P1D
            - P1W
            - P1M
            - P1Y
          description: The time period for usage limits as an ISO8601 duration string
          example: P1W
        period_label:
          type: string
          enum:
            - daily
            - weekly
            - monthly
            - yearly
          description: Human-readable label for the period
          example: weekly
        period_start:
          type: string
          format: date
          description: The start date of the current usage period
          example: '2025-11-10'
        period_end:
          type: string
          format: date
          description: The end date of the current usage period
          example: '2025-11-16'
        would_exceed_limit:
          type: boolean
          description: Whether adding another usage would exceed the limit
          example: false
      required:
        - max_uses
        - current_uses
        - remaining_uses
        - period
        - period_label
        - period_start
        - period_end
        - would_exceed_limit
    Order:
      title: Order
      description: |
        A customer order containing items and payments.
        This format replaces an older version of the order schema, and must be requested
        explicitly by passing `generic_items_array=true` as a query parameter.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the order.
    OrderDiscount:
      title: OrderDiscount
      description: An `OrderDiscount`
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the order discount.
        discount_type_code:
          type: string
          description: |
            The code for the [`DiscountType`](/endpoints/DiscountTypes).
            If the code exists, the discount will be applied. If not, an error will be returned.
          example: SUMMER23
        applicable_for:
          type: string
          description: Where the [`DiscountType`](/endpoints/DiscountTypes) is able to be applied.
          example: app_and_booking_engine
          enum:
            - app_only
            - app_and_booking_engine
        amount_type:
          type: string
          description: |
            The type of discount. For a promo code, this will always be a percentage.
          example: percentage
          enum:
            - monetary
            - percentage
        discount_amount:
          type: integer
          description: |
            The value of the discount to be applied when a [`DiscountType`](/endpoints/DiscountTypes) is used.
            This can be used as a monetary amount or percentage for an in-app discount type and is set to percentage for a promo code.
          example: 15
        calculated_amount:
          type: integer
          description: The total calculated amount of this discount.
          example: 150
        currency:
          type: string
          description: |
            The currency of the monetary discount to be applied if `amount_type` is set to `monetary` for an in-app discount type.
            This is associated with the site.
          example: gbp
        reason_code:
          type: string
          description: |
            The code for the reason the discount was applied.
          example: coupon
          enum:
            - coupon
            - general
            - predefined
            - voucher_difference
          nullable: true
        coupon_code_id:
          type: string
          description: |
            The ID of the coupon code used to add this discount, if applicable.
          format: object-id
          nullable: true
        coupon:
          type: object
          description: |
            The summary of the coupon used to add this discount, if applicable.
          $ref: '#/components/schemas/BasketCouponSummary'
          nullable: true
        applied_by:
          type: object
          description: |
            Information about the user who applied the discount. 
            If this is null, the discount was applied by the customer.
          $ref: '#/components/schemas/UserSummary'
          nullable: true
        applied_at:
          type: string
          format: date-time
          description: |
            The date and time the [`DiscountType`](/endpoints/DiscountTypes) was applied.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the discount is associated with.
      required:
        - id
        - discount_type_code
        - applicable_for
        - amount_type
        - discount_amount
        - calculated_amount
        - currency
        - reason_code
        - coupon_code_id
        - coupon
        - applied_by
        - applied_at
        - site_id
    OrderEmailSummary:
      title: OrderEmailSummary
      description: |
        A summary of an email message related to an order — including delivery,
        open and bounce status. Use the [Retrieve an order email](#operation/getOrderEmail)
        endpoint to fetch the full rendered HTML body.
      type: object
      additionalProperties: false
      required:
        - id
        - organisation_id
        - site_id
        - basket_id
        - to
        - subject
        - type
        - opened
        - bounced
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the email message.
          example: 5ed2b95f72823c4f98419f19
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the email message belongs to.
          example: 5ed2b95f72823c4f98419f10
        site_id:
          type: string
          format: uuid
          description: The ID of the site the email message belongs to.
          example: 5ed2b95f72823c4f98419f11
        customer_id:
          type: string
          format: uuid
          nullable: true
          description: The ID of the customer the email message was sent to, if known.
          example: 5ed2b95f72823c4f98419f12
        basket_id:
          type: string
          format: object-id
          description: The ID of the order (basket) this email message is attached to.
          example: 5ed2b95f72823c4f98419f13
        from:
          type: string
          nullable: true
          description: The "from" address that sent the email.
          example: bookings@example-spa.com
        to:
          type: array
          items:
            type: string
          description: The list of recipients of the email message.
          example:
            - jane.doe@example.com
        cc:
          type: array
          nullable: true
          items:
            type: string
          description: The list of CC recipients of the email message.
        bcc:
          type: array
          nullable: true
          items:
            type: string
          description: The list of BCC recipients of the email message.
        subject:
          type: string
          description: The subject line of the email message.
          example: Your booking is confirmed
        type:
          type: string
          description: |
            The type of email message — typically maps to a templated message class
            such as `BookingConfirmation` or `BookingReminder`.
          example: BookingConfirmation
        created_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the email message record was created.
          example: '2024-02-02T12:00:00+00:00'
        sent_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the email message was sent to the upstream provider.
          example: '2024-02-02T12:00:01+00:00'
        delivered_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the email message was reported as delivered.
          example: '2024-02-02T12:00:05+00:00'
        opened:
          type: boolean
          description: Whether the recipient has opened the email at least once.
          example: true
        bounced:
          type: boolean
          description: Whether the email message bounced.
          example: false
    OrderEmailMessage:
      title: OrderEmailMessage
      description: |
        A rendered email message — either retrieved from history or generated as a
        preview prior to sending.
      type: object
      additionalProperties: false
      required:
        - subject
        - email_type
        - html
      properties:
        from:
          type: string
          nullable: true
          description: The "from" address of the email message.
          example: bookings@example-spa.com
        to:
          type: array
          items:
            type: string
          description: The recipients of the email message.
          example:
            - jane.doe@example.com
        cc:
          type: array
          nullable: true
          items:
            type: string
          description: The CC recipients of the email message.
        bcc:
          type: array
          nullable: true
          items:
            type: string
          description: The BCC recipients of the email message.
        subject:
          type: string
          description: The subject line of the email message.
          example: Your booking is confirmed
        email_type:
          type: string
          description: |
            The class name of the underlying mailable that produced this email — for
            example `BookingConfirmation`.
          example: BookingConfirmation
        html:
          type: string
          description: The fully rendered HTML body of the email message.
          example: |
            <html><body><p>Hi Jane, your booking on Saturday is confirmed.</p></body></html>
    OrderExternalId:
      title: OrderExternalId
      description: Details of an external ID applied to an order.
      type: object
      additionalProperties: false
      properties:
        key:
          type: string
          description: The key of the external ID.
          example: pms_id
        name:
          type: string
          description: The name of the external ID type.
          example: PMS ID
        value:
          type: string
          description: The value of the external ID for this order.
          example: pms_123
      required:
        - key
        - name
        - value
    FiscalisationProcessorData:
      title: FiscalisationProcessorData
      type: object
      additionalProperties: true
    FiscalisationSignature:
      title: FiscalisationSignature
      type: object
      additionalProperties: false
      properties:
        caption:
          type: string
          description: The caption to be displayed with the signature.
          example: Day Totals
        format:
          type: string
          description: The format of the signature.
          enum:
            - text
            - json
            - qr_code
        raw_data:
          type: string
          description: The unformatted data for the signature.
          example: '{"qid":"83eb879e-ddc6-4c98-9520-fdd570014c48"}'
        json_data:
          type: object
          title: FiscalisationSignatureJsonData
          description: A map of key-value pairs if the format was 'json'.
          additionalProperties: true
      required:
        - caption
        - format
        - raw_data
    FiscalReceipt:
      title: FiscalReceipt
      description: Represents a fiscal receipt along with its signing status and response from the third party fiscalisation service.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the fiscal receipt.
        status:
          type: string
          description: The status of the action.
          enum:
            - in_progress
            - success
            - error
        type:
          type: string
          description: The type of the receipt. A cancellation is a refund that was issued after the basket was checked out.
          enum:
            - basket
            - payment
            - refund
            - cancellation
        document_issued_dates:
          type: array
          description: An array of date and time values when the fiscal receipt document was issued.
          items:
            type: string
            format: date-time
        is_copy:
          type: boolean
          description: Whether this receipt is a copy of another fiscal receipt, created by reprinting it.
        copy_of_fiscal_receipt_id:
          type: string
          format: mongo-id
          description: The ID of the original fiscal receipt this receipt is a copy of. Only present when `is_copy` is `true`.
        can_print:
          type: boolean
          description: |
            Whether this receipt's document can currently be printed. This is only
            applicable for sites in France, where a physical NF525 receipt must be
            issued; it is always `true` elsewhere. In France, it is `false` once the
            receipt has a newer copy, or once its document has already been issued.
        posted_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the fiscal receipt was posted to the third party integration for signing and archiving.
        integration:
          type: string
          description: The identifier of the third party integration used to sign and archive the receipt.
          example: fiskaltrust
        integration_name:
          type: string
          description: A user-friendly name for the integration.
          example: fiskaltrust
        payable:
          $ref: '#/components/schemas/PayableSummary'
        causer:
          $ref: '#/components/schemas/CauserSummary'
        lines:
          type: array
          description: An array of ledger lines that were included in this receipt.
          items:
            $ref: '#/components/schemas/LedgerLine'
        receipt_id:
          type: string
          description: The ID of the fiscal receipt in the third party integration.
          example: ft18#0015-0002
        processor_data:
          nullable: true
          description: An object of key-value pairs containing the response from the integration.
          $ref: '#/components/schemas/FiscalisationProcessorData'
        signatures:
          type: array
          nullable: true
          description: An array of signatures from the integration.
          items:
            $ref: '#/components/schemas/FiscalisationSignature'
        error:
          type: string
          description: The error message when attempting to post the receipt, if applicable
          example: Unable to connect
        created_at:
          type: string
          format: date-time
          description: The date and time the receipt was created in Trybe.
      required:
        - id
        - posted_at
        - type
        - is_copy
        - can_print
        - integration
        - integration_name
        - payable
        - lines
        - created_at
    BookingOrderItem:
      title: BookingOrderItem
      description: An item within an order that has an associated booking.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the order item.
          type: string
          format: mongo-id
        status:
          description: The confirmation status of the item.
          type: string
          enum:
            - confirmed
            - pending_confirmation
            - reserved
            - cancelled
            - waitlisted
        item_type:
          description: The type of item (offering) this order item is for.
          type: string
          enum:
            - appointment
            - area_booking
            - session
            - table_reservation
          example: appointment
        type_id:
          description: The ID of the offering.
          type: string
          format: mongo-id
        type_name:
          description: The name of the offering.
          type: string
          example: 60 minute massage
        type_product_code:
          description: The product code of the offering.
          type: string
          nullable: true
          example: MAS123
        booking_summary:
          $ref: '#/components/schemas/BookingSummary'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        booking_reserved_until:
          description: The date and time the booking is reserved until. Only applicable for bookings in the reserved state.
          type: string
          format: date-time
        total_cost:
          description: The total cost of this order item, i.e. its price multiplied by quantity.
          type: integer
          example: 595
        price:
          description: The total price of a single quantity of this order item.
          type: integer
          example: 595
        base_price:
          description: If the price has been modified, this value contains the original unit price.
          type: integer
          example: 595
        discount_amount:
          description: The amount of discount applied to this order item (already deducted from its price and total cost).
          type: integer
          example: 595
        discounts:
          description: An array of discounts applied to the item.
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        date:
          description: The date of the booking.
          type: string
          format: date
        added_by_customer:
          description: Whether this item was added to the basket by the customer.
          type: boolean
          example: true
        sold_by:
          description: The staff member responsible for selling this item.
          $ref: '#/components/schemas/SoldBy'
        is_modifiable:
          description: Determines if the item is modifiable. A booking item is modifiable if it is in the future.
          type: boolean
          example: true
        created_at:
          description: The date and time the booking was created.
          type: string
          format: date-time
        updated_at:
          description: The date and time the booking was last updated.
          type: string
          format: date-time
      required:
        - id
        - status
        - item_type
        - type_id
        - type_name
        - type_product_code
        - booking_summary
        - guests
        - total_cost
        - price
        - discount_amount
        - discounts
        - date
        - added_by_customer
        - sold_by
        - is_modifiable
        - created_at
        - updated_at
    PurchaseOrderItem:
      title: PurchaseOrderItem
      description: An item within an order that is a purchase of an item, i.e. that doesn't have a booking.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the order item.
          type: string
          format: mongo-id
        status:
          description: The confirmation status of the item.
          type: string
          enum:
            - confirmed
            - pending_confirmation
            - reserved
            - cancelled
            - waitlisted
        item_type:
          description: The type of item (offering) this order item is for.
          type: string
          enum:
            - course
            - hotel_room_reservation
            - membership
            - product
            - voucher
          example: product
        type_id:
          description: The ID of the offering.
          type: string
          format: mongo-id
        type_name:
          description: The name of the offering.
          type: string
          example: Orange Zest Moisturiser
        type_product_code:
          description: The product code of the offering.
          type: string
          nullable: true
          example: MAS123
        item_configuration:
          $ref: '#/components/schemas/ItemConfiguration'
        purchasable_details:
          $ref: '#/components/schemas/PurchasableDetails'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        reserved_until:
          description: The date and time the purchase is reserved until. Only applicable for items in the reserved state.
          type: string
          format: date-time
        total_cost:
          description: The total cost of this order item, i.e. its price multiplied by quantity.
          type: integer
          example: 595
        price:
          description: The total price of a single quantity of this order item.
          type: integer
          example: 595
        base_price:
          description: If the price has been modified, this value contains the original unit price.
          type: integer
          example: 595
        discount_amount:
          description: The amount of discount applied to this order item (already deducted from its price and total cost).
          type: integer
          example: 595
        discounts:
          description: An array of discounts applied to the item
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        added_by_customer:
          description: Whether this item was added to the basket by the customer
          type: boolean
          example: true
        sold_by:
          description: The staff member responsible for selling this item.
          $ref: '#/components/schemas/SoldBy'
        is_modifiable:
          description: Determines if the item is modifiable. An item is modifiable on the day it was added to the order.
          type: boolean
          example: true
        created_at:
          description: The date and time the item was created.
          type: string
          format: date-time
        updated_at:
          description: The date and time the item was last updated.
          type: string
          format: date-time
      required:
        - id
        - status
        - item_type
        - type_id
        - type_name
        - type_product_code
        - guests
        - total_cost
        - price
        - discount_amount
        - discounts
        - added_by_customer
        - sold_by
        - is_modifiable
        - created_at
        - updated_at
    PackageOrderItem:
      title: PackageOrderItem
      description: An item within an order that is a purchase of a package.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the order item.
          type: string
          format: mongo-id
        status:
          description: The confirmation status of the item.
          type: string
          enum:
            - confirmed
            - pending_confirmation
            - reserved
            - cancelled
            - waitlisted
        item_type:
          description: The type of item (offering) this order item is for.
          type: string
          enum:
            - package
          example: package
        type_id:
          description: The ID of the offering.
          type: string
          format: mongo-id
        type_name:
          description: The name of the offering.
          type: string
          example: Relax and Escape Spa Day
        type_product_code:
          description: The product code of the offering.
          type: string
          nullable: true
          example: MAS123
        package_items:
          type: array
          items:
            title: PackageOrderItemPackageItem
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
              booking_summary:
                $ref: '#/components/schemas/BookingSummary'
              choice_id:
                type: string
                format: object-id
              duration:
                type: integer
                nullable: true
              guests:
                type: array
                items:
                  $ref: '#/components/schemas/Guest'
              item_configuration:
                $ref: '#/components/schemas/ItemConfiguration'
              offering_id:
                type: string
                format: object-id
              offering_name:
                type: string
              offering_type:
                $ref: '#/components/schemas/OfferingType'
              option_id:
                type: string
                format: object-id
              price_change:
                type: integer
              reserved_until:
                type: string
                format: date-time
              shared_basket_item_id:
                type: string
                format: object-id
              status:
                $ref: '#/components/schemas/Status'
              time:
                type: string
                nullable: true
                example: '14:00'
            required:
              - id
              - choice_id
              - duration
              - item_configuration
              - offering_id
              - offering_name
              - offering_type
              - option_id
              - price_change
              - reserved_until
              - time
        option_budgets:
          $ref: '#/components/schemas/OptionBudget'
        guests:
          type: array
          items:
            $ref: '#/components/schemas/GuestSummary'
        total_cost:
          description: The total cost of this order item, i.e. its price multiplied by quantity.
          type: integer
          example: 595
        price:
          description: The total price of a single quantity of this order item.
          type: integer
          example: 595
        base_price:
          description: If the price has been modified, this value contains the original unit price.
          type: integer
          example: 595
        discount_amount:
          description: The amount of discount applied to this order item (already deducted from its price and total cost).
          type: integer
          example: 595
        discounts:
          description: An array of discounts applied to the item.
          type: array
          items:
            $ref: '#/components/schemas/Discount'
        date:
          description: The date of the start of the package.
          type: string
          format: date
        added_by_customer:
          description: Whether this item was added to the basket by the customer.
          type: boolean
          example: true
        sold_by:
          description: The staff member responsible for selling this item.
          $ref: '#/components/schemas/SoldBy'
        is_modifiable:
          description: Determines if the item is modifiable. A booking item is modifiable if it is in the future.
          type: boolean
          example: true
        created_at:
          description: The date and time the booking was created.
          type: string
          format: date-time
        updated_at:
          description: The date and time the booking was last updated.
          type: string
          format: date-time
      required:
        - id
        - status
        - item_type
        - type_id
        - type_name
        - type_product_code
        - guests
        - total_cost
        - price
        - discount_amount
        - discounts
        - date
        - added_by_customer
        - sold_by
        - is_modifiable
        - created_at
        - updated_at
    OrderItemDiscount:
      title: OrderItemDiscount
      description: A discount applied to a single line on an order. Each discount carries a reference to the `DiscountType` that drove it, the resulting monetary reduction, and any operator note recorded at the time. Removing the discount reverts the line's price; multiple discounts can stack on the same item.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the order item discount.
        discount_type_code:
          type: string
          description: |
            The code for the [`DiscountType`](/endpoints/DiscountTypes).
            If the code exists, the discount will be applied. If not, an error will be returned.
          example: SUMMER23
        applicable_for:
          type: string
          description: Where the [`DiscountType`](/endpoints/DiscountTypes) is able to be applied.
          example: app_and_booking_engine
          enum:
            - app_only
            - app_and_booking_engine
        amount_type:
          type: string
          description: |
            The type of discount. For a promo code, this will always be a percentage.
          example: percentage
          enum:
            - monetary
            - percentage
        discount_amount:
          type: integer
          description: |
            The value of the discount to be applied when a [`DiscountType`](/endpoints/DiscountTypes) is used.
            This can be used as a monetary amount or percentage for an in-app discount type and is set to percentage for a promo code.
          example: 15
        calculated_amount:
          type: integer
          description: The total calculated amount of this discount.
          example: 150
        currency:
          type: string
          description: |
            The currency of the monetary discount to be applied if `amount_type` is set to `monetary` for an in-app discount type.
            This is associated with the site.
          example: gbp
        reason_code:
          type: string
          description: |
            The code for the reason the discount was applied.
          example: coupon
          enum:
            - coupon
            - general
            - predefined
            - voucher_difference
          nullable: true
        coupon_code_id:
          type: string
          description: |
            The ID of the coupon code used to add this discount, if applicable.
          format: object-id
          nullable: true
        coupon:
          type: object
          description: |
            The summary of the coupon used to add this discount, if applicable.
          $ref: '#/components/schemas/BasketCouponSummary'
          nullable: true
        applied_by:
          type: object
          description: |
            Information about the user who applied the discount. 
            If this is null, the discount was applied by the customer.
          $ref: '#/components/schemas/UserSummary'
          nullable: true
        applied_at:
          type: string
          format: date-time
          description: |
            The date and time the [`DiscountType`](/endpoints/DiscountTypes) was applied.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the discount is associated with.
      required:
        - id
        - discount_type_code
        - applicable_for
        - amount_type
        - discount_amount
        - calculated_amount
        - currency
        - reason_code
        - coupon_code_id
        - coupon
        - applied_by
        - applied_at
        - site_id
    UpdateOrderLabel:
      description: Details of a single label to be added to an order.
      title: UpdateOrderLabel
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the label to be added
          type: string
          format: mongo-id
      required:
        - id
    ItemServiceChargeAmount:
      title: ItemServiceChargeAmount
      description: Represents an amount of service charge for a single item in an order.
      type: object
      additionalProperties: false
      properties:
        item_id:
          type: string
          format: mongo-id
          description: The ID of the item.
        amount:
          type: integer
          description: The amount of service charge for this item, in minor units.
          example: 595
      required:
        - item_id
        - amount
    OrderMessageSummary:
      title: OrderMessageSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the order message.
        type:
          type: string
          description: The medium through which the order message is sent.
          enum:
            - email
            - sms
        recipients:
          type: array
          description: The recipients of the order message.
          items:
            type: string
            description: |
              The recipient of the order message. This can be an email address or a phone number, depending on the type of the order message.
            example: janedoe@email.uk
        summary:
          type: string
          description: |
            A summary of the order message. For an email, this will be the subject, and for an SMS message, this will be an excerpt of the message.
          example: Hello! Thank you for your order!
        message_type:
          type: string
          description: The type of message the order message is.
          enum:
            - basket_confirmed
            - basket_cancelled
            - basket_cancelled_with_charge
            - basket_cancelled_without_charge
            - basket_reminder
            - basket_follow_up
            - pay_by_link_request
        created_at:
          type: string
          format: date-time
          description: The date and time the order message was created.
          example: '2024-02-02T12:00:00Z'
        sent_at:
          type: string
          format: date-time
          description: The date and time the order message was sent.
          example: '2024-02-02T12:00:00Z'
        delivered_at:
          type: string
          format: date-time
          description: The date and time the email was delivered. For an SMS message, this will be null.
          nullable: true
          example: '2024-02-02T12:00:00Z'
        opened:
          type: boolean
          description: Whether the email was opened. For an SMS message, this will be null.
          nullable: true
          example: true
        bounced:
          type: boolean
          description: Whether the email bounced. For an SMS message, this will be null.
          nullable: true
          example: false
      required:
        - id
        - type
        - recipients
        - summary
        - message_type
        - created_at
        - sent_at
        - delivered_at
        - opened
        - bounced
    AutomatedOrderMessage:
      title: AutomatedOrderMessage
      type: object
      additionalProperties: false
      properties:
        next_reminder_sms_date:
          type: string
          format: date-time
          description: The date and time for when the next reminder SMS message will be sent.
          nullable: true
        next_followup_sms_date:
          type: string
          format: date-time
          description: The date and time for when the next follow-up SMS message will be sent.
          nullable: true
      required:
        - next_reminder_sms_date
        - next_followup_sms_date
    SmsMessageSummary:
      title: SmsMessageSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the SMS message.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the SMS message is associated with.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the SMS message is associated with.
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer the SMS message was sent to.
        basket_id:
          type: string
          format: object-id
          description: The ID of the basket the SMS message is associated with.
        order_ref:
          type: string
          description: The reference of the order the SMS message is associated with.
          example: TRY00
        from:
          type: string
          description: The sender of the SMS message.
          example: Trybe
        to:
          type: string
          description: The recipient of the SMS message. This is a valid mobile number.
          example: '+447123456789'
        message:
          type: string
          description: |
            The contents of the SMS message.
        message_type:
          type: string
          description: The type of message the SMS message is.
          enum:
            - basket_confirmed
            - basket_cancelled_with_charge
            - basket_cancelled_without_charge
            - basket_reminder
            - basket_follow_up
            - pay_by_link_request
            - billing_details_request
        message_delivered:
          type: boolean
          description: Whether the SMS message was successfully delivered.
          example: true
        price:
          type: integer
          description: The price of the SMS message.
          example: 4
        created_at:
          type: string
          format: date-time
          description: The date and time the SMS message was created.
          example: '2024-02-02T12:00:00Z'
        sent_at:
          type: string
          format: date-time
          description: The date and time the SMS message was sent.
          example: '2024-02-02T12:00:00Z'
      required:
        - id
        - organisation_id
        - site_id
        - customer_id
        - basket_id
        - from
        - to
        - message
        - message_type
        - message_delivered
        - price
        - created_at
        - sent_at
    SmsMessageParams:
      title: SmsMessageParams
      type: object
      description: The parameters to be used in the SMS message.
      additionalProperties: false
      properties:
        cancellation_charge:
          type: boolean
          description: Whether there is a cancellation charge for the order.
          example: true
    SmsMessagePreview:
      title: SmsMessagePreview
      type: object
      additionalProperties: false
      properties:
        message:
          type: string
          description: The contents of the SMS message.
          example: |
            Hi! Your order has been confirmed. We look forward to seeing you on Saturday 3rd February at 12pm.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the SMS message is associated with.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the SMS message is associated with.
      required:
        - message
        - site_id
        - organisation_id
    SmsMessageSuppressionStatus:
      title: SmsMessageSuppressionStatus
      type: object
      additionalProperties: false
      properties:
        suppress_reminder_sms:
          type: boolean
          description: Whether the reminder SMS message has been suppressed.
          example: true
        suppress_followup_sms:
          type: boolean
          description: Whether the follow-up SMS message has been suppressed.
          example: true
      required:
        - suppress_reminder_sms
        - suppress_followup_sms
    schemas_CustomerLabel-2:
      title: CustomerLabel
      description: A label assigned to a customer.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the label.
          type: string
        color:
          description: The color of the label.
          type: string
        name:
          description: The name of the label.
          type: string
      required:
        - id
        - name
    schemas_CustomerSummary-2:
      title: CustomerSummary
      description: A lightweight projection of a `Customer` containing only the fields needed to display the guest in an order context (name, contact, ID). Use the full `Customer` endpoint when you need addresses, memberships, marketing preferences or payment methods.
      type: object
      additionalProperties: false
      properties:
        id:
          description: The ID of the customer.
          type: string
        first_name:
          description: The first name of the customer.
          type: string
        last_name:
          description: The last name of the customer.
          type: string
        full_name:
          description: The full name of the customer.
          type: string
        email:
          description: The email address of the customer.
          type: string
        phone:
          description: The phone number of the customer.
          type: string
        labels:
          description: A list of labels assigned to the customer.
          type: array
          items:
            $ref: '#/components/schemas/schemas_CustomerLabel-2'
      required:
        - id
        - first_name
        - last_name
        - full_name
        - email
        - phone
        - labels
    schemas_Category-3:
      title: Category
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the category.
        name:
          type: string
          description: The name of the category.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the category belongs to.
        voucher_applicable:
          type: boolean
          description: |
            Whether the category can be selected when issuing vouchers.
      required:
        - id
        - name
        - organisation_id
        - voucher_applicable
    requestBody-content-application~1json-schema:
      title: UpdateCategory
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          description: |
            Display name of the category, shown to customers on the
            storefront and to staff in the admin UI. Categories
            group offerings (treatments, classes, products) for
            navigation and reporting. 1-120 characters; must not
            contain HTML.
          example: Massages
        voucher_applicable:
          type: boolean
          description: |
            Whether the category can be selected when issuing vouchers.
    CategoryLocaleStrings:
      title: CategoryLocaleStrings
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
          description: The localised name for this category in the given locale.
      required:
        - name
    CustomPaymentType:
      title: CustomPaymentType
      type: object
      additionalProperties: false
      description: |
        A `CustomPaymentType` lets operators record tenders that are not
        natively handled by Trybe's payment processors — for example,
        third-party gift cards, hotel PMS prepayments, or arbitrary
        "cash equivalent" payments. Custom payment types are owned by an
        `Organisation` and can be attached to one or more of its `Site`s.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the `CustomPaymentType`.
          example: 5f8d944e79c9f341846e807a
        name:
          type: string
          description: |
            Display name shown to staff when accepting payment. 1-120
            characters; required.
          example: Hotel Folio
        kind:
          type: string
          enum:
            - pms_prepaid
            - voucher
            - prepayment
          nullable: true
          description: |
            Optional classification used to drive special handling.

            - `pms_prepaid` — payment is being charged back to a connected
              Property Management System folio.
            - `voucher` — payment redeems an external (non-Trybe) voucher.
            - `prepayment` — payment was taken outside Trybe ahead of the
              appointment.

            When omitted, the payment type behaves like a generic tender.
          example: pms_prepaid
        fiscalisation_type:
          type: string
          enum:
            - unknown
            - cash
            - debit_card
            - credit_card
            - voucher
            - online
          nullable: true
          description: |
            Optional mapping used when posting to fiscalisation
            integrations that require a tender-type code (e.g.
            Fiskaltrust, eduPOS). Defaults to `unknown` when not set.
          example: cash
      required:
        - id
        - name
    DateSet:
      title: DateSet
      type: object
      additionalProperties: false
      required:
        - id
        - dates
        - name
        - organisation_id
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the date set.
        dates:
          type: array
          description: The dates in the date set.
          items:
            type: object
            title: DateSetDate
            additionalProperties: false
            required:
              - date
              - label
            properties:
              date:
                type: string
                format: date
              label:
                type: string
        name:
          type: string
          description: |
            Label for the date set, shown wherever the set is referenced
            in the admin UI (date pickers, coupon validity, opening
            exceptions). Use a meaningful label like "Bank holidays"
            or "Closed for refurb". 1-120 characters.
          example: Bank holidays
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the date set belongs to.
    dates:
      type: array
      description: The dates in the date set.
      items:
        type: object
        title: DateSetDate
        additionalProperties: false
        required:
          - date
          - label
        properties:
          date:
            type: string
            format: date
          label:
            type: string
    properties-name:
      type: string
      description: |
        Label for the date set, shown wherever the set is referenced
        in the admin UI (date pickers, coupon validity, opening
        exceptions). Use a meaningful label like "Bank holidays"
        or "Closed for refurb". 1-120 characters.
      example: Bank holidays
    patch-requestBody-content-application~1json-schema:
      title: UpdateDateSet
      type: object
      additionalProperties: false
      properties:
        dates:
          $ref: '#/components/schemas/dates'
        name:
          $ref: '#/components/schemas/properties-name'
    SessionRecurrenceGroup:
      title: SessionRecurrenceGroup
      type: object
      description: A `SessionRecurrenceGroup` object
      additionalProperties: false
      required:
        - capacity
        - deleted_at
        - id
        - name
        - recurrence_end
        - recurrence_start
        - room
        - session_type_id
        - start_time
        - start_times
        - weekdays
      properties:
        capacity:
          type: integer
          description: The capacity of each session in this group.
          example: 12
        deleted_at:
          type: string
          format: date-time
          nullable: true
          description: A timestamp of when the this was deleted.
        id:
          type: string
          format: object-id
          description: The ID of the recurrence group.
          example: 609bd745e4358066f7061d82
        name:
          type: string
          description: An option name for the recurrence group.
          example: Mondays with Adrienne
        practitioner:
          description: The practitioner who leads the sessions in this group.
          $ref: '#/components/schemas/PractitionerSummary'
        recurrence_end:
          type: string
          nullable: true
          format: date
          description: The end date of the recurrence group.
          example: '2021-05-10'
        recurrence_start:
          type: string
          nullable: true
          format: date
          description: The start date of the recurrence group.
          example: '2021-04-10'
        room:
          description: The room where the sessions in this group take place.
          $ref: '#/components/schemas/RoomSummary'
        session_type_id:
          description: The ID of the `SessionType` this `SessionRecurrenceGroup` belongs to.
          type: string
          format: object-id
        start_time:
          type: string
          nullable: true
          description: The start time of each occurrence, in 24 hour format
          example: '16:00'
          deprecated: true
        start_times:
          type: array
          minItems: 1
          description: An array of start times
          items:
            type: object
            title: StartTime
            additionalProperties: false
            required:
              - id
              - value
            properties:
              id:
                type: string
                format: object-id
                description: The ID of the start time
              value:
                type: string
                description: The start time of each occurrence, in 24 hour format
                example: '16:00'
        weekdays:
          type: array
          description: The weekdays this rule applies to
          items:
            type: string
            example: monday
    CreateSessionRecurrenceGroup:
      title: CreateSessionRecurrenceGroup
      type: object
      additionalProperties: false
      required:
        - session_type_id
      properties:
        name:
          type: string
          description: An option name for the recurrence group.
          example: Mondays with Adrienne
        practitioner_id:
          description: The practitioner who leads the sessions in this group.
          type: string
          format: object-id
        room_id:
          description: The room where the sessions in this group take place.
          type: string
          format: object-id
        weekdays:
          type: array
          description: The weekdays sessions in this group take place.
          items:
            type: string
            example: monday
        start_time:
          type: string
          description: The start time of each occurrence in this group, in 24 hour format.
          example: '16:00'
        start_times:
          type: array
          items:
            title: CreateSessionRecurrenceGroupStartTime
            type: object
            additionalProperties: false
            properties:
              value:
                type: string
                example: '12:00'
            required:
              - value
        capacity:
          type: integer
          description: The capacity of each session in this group.
          example: 12
        recurrence_start:
          type: string
          format: date
          nullable: true
          description: The start date of the recurrence group.
          example: '2021-04-10'
        recurrence_end:
          type: string
          format: date
          nullable: true
          description: The end date of the recurrence group.
          example: '2021-05-10'
        session_type_id:
          description: The `SessionType` that this `SessionRecurrenceGroup` belongs to.
          type: string
          format: object-id
    UpdateSessionRecurrenceGroup:
      title: UpdateSessionRecurrenceGroup
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          description: An option name for the recurrence group.
          example: Mondays with Adrienne
        practitioner_id:
          description: The practitioner who leads the sessions in this group.
          type: string
          example: 5f184bb0b6ecff2e8157bf27
        room_id:
          description: The room where the sessions in this group take place.
          type: string
          example: 5dcb47800000000000000010
        weekdays:
          type: array
          description: The weekdays sessions in this group take place.
          items:
            type: string
            example: monday
        start_time:
          type: string
          description: The start time of each occurrence in this group, in 24 hour format.
          example: '16:00'
        start_times:
          type: array
          items:
            title: UpdateSessionRecurrenceGroupStartTime
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
              value:
                type: string
                example: '12:00'
            required:
              - value
        capacity:
          type: integer
          description: The capacity of each session in this group.
          example: 12
        recurrence_start:
          type: string
          format: date
          nullable: true
          description: The start date of the recurrence group.
          example: '2021-04-10'
        recurrence_end:
          type: string
          format: date
          nullable: true
          description: The end date of the recurrence group.
          example: '2021-05-10'
    CreatedAt:
      type: string
      format: date-time
      description: A datetime string of when the resource was created.
    UpdatedAt:
      type: string
      format: date-time
      description: A datetime string of when the resource was last updated.
    SessionBooking:
      title: SessionBooking
      description: Describes a booking for a session.
      type: object
      additionalProperties: false
      required:
        - id
        - checked_in_at
        - checked_out_at
        - customer_id
        - email
        - first_name
        - guests
        - intake_form_required
        - intake_forms_completed
        - is_no_show
        - last_name
        - order_id
        - order_item_id
        - order_ref
        - organisation_id
        - phone
        - session_id
        - session_type_id
        - session_type_name
        - site_id
        - stage
        - status
        - created_at
        - updated_at
      properties:
        id:
          type: string
          description: The ID of the session.
          example: 5dcb47800000000000000000
        checked_in_at:
          type: string
          format: date-time
          nullable: true
          description: The time this booking was checked in.
          example: '2022-03-02T09:00:00+00:00'
        checked_out_at:
          type: string
          format: date-time
          nullable: true
          description: The time this booking was checked out.
          example: '2022-03-02T10:00:00+00:00'
        customer_id:
          type: string
          description: The ID of the customer this booking is for.
          example: 5dcb47800000000000000020
        email:
          type: string
          description: The email address of the customer.
          example: janedoe@example.com
        first_name:
          type: string
          description: The first name of the customer.
          example: Jane
        guests:
          type: array
          items:
            $ref: '#/components/schemas/Guest'
        intake_forms_completed:
          type: boolean
          description: Whether the required intake form has been completed.
          example: false
        intake_form_required:
          type: boolean
          description: Whether the session booking requires an intake form to be completed.
          example: true
        is_no_show:
          type: boolean
          description: Whether this booking was marked as a no-show.
        last_name:
          type: string
          description: The last name of the customer.
          example: Doe
        order_id:
          type: string
          description: The ID of the order associated with this session.
          example: 5dcb47800000000000000009
        order_item_id:
          type: string
          description: The ID of the order item associated with this session.
          example: 5dcb47800000000000000019
        order_ref:
          type: string
          description: The order reference associated with this session.
          example: TRY00
        organisation_id:
          type: string
          description: The ID of the organisation the session booking belongs to.
          example: 00000000-0000-0000-0000-000000000000
        phone:
          type: string
          description: The customer's phone number.
          example: '+447727123456'
        session_id:
          type: string
          description: The ID of the session this booking is for.
          example: 5dcb47800000000000001111
        session_type_id:
          type: string
          description: The ID of the session type.
          example: 5dcb47800000000000001234
        session_type_name:
          type: string
          description: The name of the session type.
          example: Spa access
        site_id:
          type: string
          description: The ID of the site the session booking belongs to.
          example: 00000000-0000-0000-0000-111111111111
        stage:
          type: string
          description: The current stage of the order the session belongs to.
          enum:
            - not_arrived
            - arrived
            - in_treatment
            - checked_out
        status:
          type: string
          description: The status of the booking.
          example: none
          enum:
            - new
            - in_progress
            - confirmed
            - waitlisted
        created_at:
          $ref: '#/components/schemas/CreatedAt'
        updated_at:
          $ref: '#/components/schemas/UpdatedAt'
    schemas_Session:
      title: Session
      description: Details of a single `Session`.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: |
            Stable identifier for the session occurrence. A `Session` is
            one scheduled instance of a `SessionType` — bookings are made
            against this `id`, not against the underlying type or
            recurrence group.
          example: 5dcb47800000000000000010
        bookings:
          type: array
          description: If requested, an array of bookings for this session.
          items:
            $ref: '#/components/schemas/SessionBooking'
        capacity:
          type: integer
          example: 10
          description: The total capacity of the session.
        currency:
          type: string
          description: The ISO-4217 currency code in lower case.
          example: gbp
        duration:
          type: integer
          example: 60
          description: The duration of the session.
        end_time:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
          description: The date and time the session ends.
        max_baskets:
          type: integer
          nullable: true
          example: 1
          description: The maximum number of baskets that may have bookings for this session.
        num_checked_in:
          type: integer
          description: If bookings are included, this is the number of bookings that have been checked in.
          example: 12
        num_no_show:
          type: integer
          description: If bookings are included, this is the number of bookings that have marked as no-show.
          example: 2
        num_waitlisted:
          type: integer
          example: 2
          description: The number of customers currently on the waiting list for this session.
        organisation_id:
          type: string
          description: |
            Organisation the session belongs to. Sessions are scoped to a
            single organisation and are invisible to API callers from
            other organisations.
          example: 00000000-0000-0000-0000-000000000000
        practitioner:
          $ref: '#/components/schemas/PractitionerSummary'
          nullable: true
        practitioner_id:
          type: string
          description: |
            The practitioner scheduled to lead this session. `null` for
            sessions that don't require a specific staff member (e.g. a
            free-access spa slot). Must reference an active practitioner
            on `site_id`.
          example: 5dcb47800000000000000010
          nullable: true
        price:
          type: integer
          description: The cost of the session, in the smallest denomination (eg pence or cents).
          example: 595
        remaining_capacity:
          type: integer
          example: 4
          description: The remaining capacity of the session.
        room:
          $ref: '#/components/schemas/RoomSummary'
        room_id:
          type: string
          description: |
            The room the session takes place in. Must reference a room
            configured on `site_id`. Used by the staff console to colour
            the session in the schedule view and to enforce
            per-room capacity caps.
          example: 5dcb47800000000000000010
        session_type_id:
          type: string
          description: |
            The `SessionType` this session is an occurrence of. Inherits
            defaults (default capacity, default duration, default price)
            from this type unless overridden on the session itself.
          example: 5dcb47800000000000000010
        session_type_name:
          type: string
          description: |
            Cached display name copied from the parent `SessionType` at
            the time the session was created. Useful for reporting where
            the type may since have been renamed.
          example: Spa access
        site_id:
          type: string
          description: |
            Site the session is hosted at. Sessions never span more than
            one site; bookings on the session inherit this `site_id` for
            rota and revenue-reporting purposes.
          example: 5dcb47800000000000000010
        start_time:
          type: string
          format: date-time
          example: '2019-01-15T11:00:00+01:00'
          description: The date and time the session starts.
        waitlist_enabled:
          type: boolean
          example: true
          description: Whether the waitlist is enabled for this session.
        max_waitlist_size:
          type: integer
          nullable: true
          description: The maximum number of customers allowed on the waitlist for this session. Null means the waitlist is unlimited.
          example: 10
        created_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
          description: The date and time the session was created.
        deleted_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
          description: The date and time the session was deleted (cancelled).
        updated_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00+01:00'
          description: The date and time the session was last updated.
      required:
        - id
        - capacity
        - currency
        - duration
        - end_time
        - max_baskets
        - num_checked_in
        - num_no_show
        - num_waitlisted
        - organisation_id
        - practitioner
        - practitioner_id
        - price
        - remaining_capacity
        - room
        - room_id
        - session_type_id
        - session_type_name
        - site_id
        - start_time
        - waitlist_enabled
        - max_waitlist_size
        - created_at
        - updated_at
    SessionWaitlistEntry:
      title: SessionWaitlistEntry
      description: A single booking currently queued on a session's waitlist.
      type: object
      additionalProperties: false
      properties:
        position:
          type: integer
          description: The booking's 1-based position in the waitlist queue.
          example: 1
        booking_id:
          type: string
          format: object-id
          description: The id of the waitlisted `SessionBooking`.
        order_ref:
          type: string
          nullable: true
          description: The order reference of the basket the booking belongs to.
          example: AB2SYY
        name:
          type: string
          nullable: true
          description: The customer's full name, as recorded on the basket.
          example: Jane Doe
        num_customers:
          type: integer
          description: The number of customers in this booking. Minimum 1.
          example: 1
        waitlisted_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the booking joined the waitlist.
      required:
        - position
        - booking_id
        - order_ref
        - name
        - num_customers
        - waitlisted_at
    SessionWaitlistPromotion:
      title: SessionWaitlistPromotion
      description: A booking that was previously on a session's waitlist and has since been promoted (confirmed).
      type: object
      additionalProperties: false
      properties:
        booking_id:
          type: string
          format: object-id
          description: The id of the promoted `SessionBooking`.
        order_ref:
          type: string
          nullable: true
          description: The order reference of the basket the booking belongs to.
          example: EF4UAA
        name:
          type: string
          nullable: true
          description: The customer's full name, as recorded on the basket.
          example: Alex Brown
        waitlisted_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the booking joined the waitlist.
        promoted_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the booking was promoted (confirmed) off the waitlist.
      required:
        - booking_id
        - order_ref
        - name
        - waitlisted_at
        - promoted_at
    SessionWaitlistLogEntry:
      title: SessionWaitlistLogEntry
      description: A waitlist-related entry from a session's activity log.
      type: object
      additionalProperties: false
      properties:
        level:
          type: string
          description: The log entry's severity level.
          example: info
        message:
          type: string
          description: The log entry's message.
          example: Booking (AB2SYY) was moved from the wait list.
        timestamp:
          type: string
          format: date-time
          nullable: true
          description: The date and time the log entry was recorded.
      required:
        - level
        - message
        - timestamp
    SessionWaitlist:
      title: SessionWaitlist
      description: A support/admin-facing view of a `Session`'s waitlist, its current queue, recent promotions off the waitlist, and related session-log entries.
      type: object
      additionalProperties: false
      properties:
        session_id:
          type: string
          format: object-id
          description: The `Session` id this waitlist belongs to.
        capacity:
          type: integer
          description: The total capacity of the session.
          example: 2
        num_booked:
          type: integer
          description: The total number of customers currently booked onto the session, regardless of checkout status.
          example: 2
        remaining_capacity:
          type: integer
          description: The remaining capacity of the session.
          example: 0
        waitlist_enabled:
          type: boolean
          description: Whether the waitlist is currently available for this session.
          example: true
        num_waitlisted:
          type: integer
          description: The number of customers currently on the waiting list for this session.
          example: 2
        waitlist:
          type: array
          description: Bookings currently on the waitlist, ordered oldest first — queue position 1 is next to be promoted.
          items:
            $ref: '#/components/schemas/SessionWaitlistEntry'
        promotions:
          type: array
          description: Bookings that were previously on the waitlist and have since been promoted (confirmed), ordered oldest promotion first.
          items:
            $ref: '#/components/schemas/SessionWaitlistPromotion'
        logs:
          type: array
          description: Waitlist-related entries from the session's activity log.
          items:
            $ref: '#/components/schemas/SessionWaitlistLogEntry'
      required:
        - session_id
        - capacity
        - num_booked
        - remaining_capacity
        - waitlist_enabled
        - num_waitlisted
        - waitlist
        - promotions
        - logs
    Currency:
      type: string
      description: The ISO-4217 currency code in lower case
      example: gbp
    SessionPriceRule:
      title: SessionPriceRule
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the price rule.
        session_type_id:
          type: string
          format: object-id
          description: The ID of the session type the price rule relates to.
        date_from:
          type: string
          format: date
          description: The rule should apply to sessions on or after this date.
          example: '2020-02-01'
        date_to:
          type: string
          format: date
          description: The rule should not apply to sessions after this date.
          example: '2020-04-01'
        weekdays:
          type: array
          description: The weekdays that this rule should apply to.
          items:
            type: string
            example: monday
        time_from:
          type: string
          description: The rule should apply to sessions starting on or after this time.
          example: '16:00'
        time_to:
          type: string
          description: The rule should apply to sessions starting before this time.
          example: '17:00'
        price:
          type: integer
          description: The price of the session.
          example: 1500
      required:
        - id
        - session_type_id
        - date_from
        - date_to
        - weekdays
        - time_from
        - time_to
        - price
    SessionType:
      title: SessionType
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: |
            Unique identifier of the session type. Returned from
            `createSessionType`; used to look up the type, manage its
            recurrence groups, set up bookings, and copy it.
        name:
          type: string
          description: The name of this session type
          example: Vinyasa yoga
        description:
          type: string
          description: A description of the session type
          example: A dynamic form of yoga
        product_code:
          type: string
          description: A custom product code for the session type.
          example: MAS123
        currency:
          $ref: '#/components/schemas/Currency'
        external_id:
          type: string
          nullable: true
          description: An external identifier for this offering, used by integrations to map this `SessionType` to an external system.
          example: ext-yoga-vinyasa
        hidden_on_schedule:
          type: boolean
          description: |
            When true, this session type is excluded from the staff
            schedule view in the admin UI even though sessions are still
            visible to customers and bookable. Used to keep operational
            sessions (e.g. private member-only programmes) off the main
            calendar without making them unbookable.
          example: false
        image_id:
          type: string
          nullable: true
          format: uuid
          description: |
            Media ID of the hero image for the session type, shown on the
            storefront listing and detail page. Upload via
            [`createMedia`](/endpoints/Media#createMedia) first and pass
            the returned ID here. Pass `null` to remove the image.
        image:
          $ref: '#/components/schemas/Media'
        offered_online:
          type: boolean
          description: Whether this session type is bookable online
        private:
          type: boolean
          description: Whether this is private. When private, it is accessible from the URL but doesn't appear on category pages and isn't indexed on search engines.
        site_id:
          type: string
          format: uuid
          description: |
            Identifier of the site this session type is published at.
            Session types are scoped per site so each venue can run its
            own programme; the type's bookings, capacity, and pricing
            are managed against this site.
        duration:
          type: integer
          example: 60
          description: The duration of the session type.
        max_baskets_per_session:
          type: integer
          example: 1
          description: Limit the number of baskets that may create bookings for a single session.
        max_advance_bookings_interval:
          type: string
          description: The maximum time before a session's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2W
        min_advance_bookings_interval:
          type: string
          description: The minimum time before a session's start time that it may be booked, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2D
        customers_only:
          type: boolean
          description: Whether this session requires the customer to be logged in to book.
          example: false
        members_only:
          type: boolean
          description: Whether this session requires an active membership in order to book.
          example: true
        max_bookings_per_member:
          type: integer
          description: The maximum number of bookings a member may make on a single session.
          example: 1
        permitted_membership_type_ids:
          type: array
          description: |
            If this session is for members only, this property may be used to restrict the offering further
            so it may only be booked by active members with of one of the given membership types.
          items:
            type: string
        membership_booking_windows_enabled:
          type: boolean
          description: Whether membership-specific booking windows should be enabled for this session type.
          example: true
        membership_booking_windows:
          type: array
          items:
            $ref: '#/components/schemas/MembershipBookingWindow'
        customer_cancellation_permitted:
          description: Whether bookings of this type may be cancelled online by customers. A value of `unpaid` means this booking my be cancelled only if no payments have been recorded against the order it is part of.
          $ref: '#/components/schemas/customerCancellationPermitted'
        customer_cancellation_min_duration:
          type: string
          description: The minimum duration that must be left before the booking in order for the customer to cancel, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
        customer_reschedule_permitted:
          description: Whether bookings of this type may be rescheduled online by customers. A value of `unpaid` means this booking may be rescheduled only if no payments have been recorded against the order it is part of.
          $ref: '#/components/schemas/customerReschedulePermitted'
        customer_reschedule_min_duration:
          type: string
          description: The minimum duration that must be left before the booking in order for the customer to reschedule, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P7D
        waitlist_enabled:
          type: boolean
          example: true
          description: Whether the waitlist is enabled for sessions of this type.
        max_waitlist_size:
          type: integer
          nullable: true
          description: The maximum number of customers allowed on the waitlist for sessions of this type. Null means the waitlist is unlimited.
          example: 10
        min_guests:
          type: integer
          description: The minimum guests allowed in a booking for this session
          example: 1
        max_guests:
          type: integer
          description: The maximum guests allowed in a booking for this session
          example: 2
        max_per_basket:
          type: integer
          nullable: true
          description: |
            Maximum number of times this session type can appear in a
            single basket. Null = unlimited. Use to throttle blanket
            bookings of capacity-constrained sessions.
          example: 4
        max_per_guest:
          type: integer
          nullable: true
          description: |
            Maximum number of times this session type can be assigned to
            a single guest within a basket. Null = unlimited. Defends
            against accidental duplicate bookings of the same guest.
          example: 2
        price_rules:
          type: array
          description: The rules defining prices for this session type.
          items:
            $ref: '#/components/schemas/SessionPriceRule'
        yield_management:
          $ref: '#/components/schemas/YieldManagement'
        standard_price:
          type: integer
          nullable: true
          description: |
            The standard price for this session type, in the smallest
            currency unit (e.g. pence). `null` if a standard price hasn't
            been configured — this is distinct from a price of zero.
          example: 5000
        category_ids:
          description: The category IDs associated with this session type
          type: array
          items:
            type: string
        categories:
          description: The category associated with this session type
          type: array
          items:
            $ref: '#/components/schemas/schemas_Category-2'
        recurrence_groups:
          description: An array of recurrence groups for this session type
          deprecated: true
          type: array
          items:
            $ref: '#/components/schemas/SessionRecurrenceGroup'
        meta:
          title: Meta
          type: object
          additionalProperties: false
          properties:
            title:
              type: string
              nullable: true
              description: The meta title of this offering. If not specified, it falls back to the name of the offering.
            description:
              type: string
              nullable: true
              description: The meta description of this offering. If not specified, it falls back to the description of the offering.
        upsell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        cross_sell_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        related_retail_offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        revenue_centre:
          type: string
          description: The revenue centre to assign revenue to for this offering
          example: spa
        include_pricing_on_calendar:
          type: boolean
          description: Whether the booking engine calendar should display pricing under each date
        visibility:
          type: string
          description: |
            Visibility on the shopfront. `public` = listed in search and
            browse; `link_only` = bookable only via direct link (excluded
            from search/browse); `private` = admin-only, never offered to
            customers.
          example: public
          enum:
            - link_only
            - private
            - public
        updated_at:
          type: string
          format: date-time
          description: The time and date that the appointment type was last updated.
          example: '2020-02-24T12:00:00+01:00'
        deleted_at:
          type: string
          nullable: true
          format: date-time
          description: The time and date that the appointment type was archived.
          example: '2020-02-24T12:00:00+01:00'
      required:
        - id
        - name
        - description
        - product_code
        - currency
        - external_id
        - image_id
        - offered_online
        - private
        - site_id
        - duration
        - max_baskets_per_session
        - max_advance_bookings_interval
        - min_advance_bookings_interval
        - members_only
        - max_bookings_per_member
        - membership_booking_windows_enabled
        - membership_booking_windows
        - customer_cancellation_permitted
        - customer_cancellation_min_duration
        - customer_reschedule_permitted
        - customer_reschedule_min_duration
        - waitlist_enabled
        - max_waitlist_size
        - min_guests
        - max_guests
        - max_per_basket
        - max_per_guest
        - price_rules
        - standard_price
        - yield_management
        - category_ids
        - categories
        - meta
        - upsell_offerings
        - cross_sell_offerings
        - related_retail_offerings
        - revenue_centre
        - include_pricing_on_calendar
        - visibility
        - updated_at
        - deleted_at
    SessionTypeResponse:
      title: SessionTypeResponse
      type: object
      additionalProperties: false
      required:
        - data
      properties:
        data:
          $ref: '#/components/schemas/SessionType'
    ShopSiteCustomPaymentType:
      title: ShopSiteCustomPaymentType
      type: object
      additionalProperties: false
      required:
        - id
        - name
      properties:
        id:
          type: string
        fiscalisation_type:
          type: string
        kind:
          type: string
        name:
          type: string
    ShopSiteCustomerSearchConfig:
      title: ShopSiteCustomerSearchConfig
      type: object
      additionalProperties: false
      required:
        - sources
      properties:
        sources:
          type: array
          items:
            title: ShopSiteCustomerSearchConfigSource
            type: object
            additionalProperties: false
            required:
              - key
              - name
              - supported_fields
            properties:
              key:
                type: string
              name:
                type: string
              supported_fields:
                type: array
                items:
                  type: string
    ShopSiteEmailSettings:
      title: ShopSiteEmailSettings
      type: object
      additionalProperties: false
      properties:
        collect_email_addresses:
          type: boolean
        follow_up_emails_enabled:
          type: boolean
        follow_up_emails_days_after:
          type: integer
        follow_up_emails_time:
          type: string
          nullable: true
          example: '15:00'
        hide_manage_order:
          type: boolean
        qr_codes_enabled:
          type: boolean
        reminder_emails_enabled:
          type: boolean
        reminder_emails_days_ahead:
          type: integer
        reminder_emails_time:
          type: string
          nullable: true
          example: '15:00'
        auto_send_order_summary_on_checkout:
          type: boolean
        visibility_settings:
          title: SiteEmailSettingsVisibilitySettings
          type: object
          additionalProperties: false
          properties:
            basket_confirmed:
              title: SiteEmailSettingsVisibilitySettingsBasketConfirmed
              type: object
              additionalProperties: false
              properties:
                show_day_of_week:
                  type: boolean
                show_end_times:
                  type: boolean
                show_guest_names:
                  type: boolean
                show_practitioner_names:
                  type: boolean
            basket_reminder:
              title: SiteEmailSettingsVisibilitySettingsBasketReminder
              type: object
              additionalProperties: false
              properties:
                show_day_of_week:
                  type: boolean
                show_end_times:
                  type: boolean
                show_guest_names:
                  type: boolean
                show_practitioner_names:
                  type: boolean
            order_summary:
              title: SiteEmailSettingsVisibilitySettingsOrderSummary
              type: object
              additionalProperties: false
              properties:
                show_day_of_week:
                  type: boolean
                show_end_times:
                  type: boolean
                show_guest_names:
                  type: boolean
                show_practitioner_names:
                  type: boolean
            new_order:
              title: SiteEmailSettingsVisibilitySettingsNewOrder
              type: object
              additionalProperties: false
              properties:
                show_day_of_week:
                  type: boolean
                show_end_times:
                  type: boolean
                show_guest_names:
                  type: boolean
                show_practitioner_names:
                  type: boolean
    ShopSiteFeatures:
      title: ShopSiteFeatures
      type: object
      additionalProperties: false
      properties:
        support_wearable_payments:
          type: boolean
    ShopSiteOpeningHour:
      title: ShopSiteOpeningHour
      type: object
      additionalProperties: false
      required:
        - time_from
        - time_to
        - weekday
      properties:
        time_from:
          type: string
        time_to:
          type: string
        weekday:
          type: string
    ShopSiteStripeConfig:
      title: ShopSiteStripeConfig
      deprecated: true
      type: object
      additionalProperties: false
      properties:
        account_id:
          type: string
        account_type:
          type: string
    ShopSitePaymentConfig:
      title: ShopSitePaymentConfig
      type: object
      additionalProperties: false
      required:
        - default_processor
        - should_show_stripe
      properties:
        default_processor:
          type: string
        should_show_stripe:
          type: boolean
        stripe:
          $ref: '#/components/schemas/ShopSiteStripeConfig'
        terminal_payments:
          title: SiteTerminalPayments
          type: object
          additionalProperties: false
          required:
            - enabled
            - processor
          properties:
            enabled:
              type: boolean
            processor:
              type: string
              nullable: true
    ShopSitePmsIntegration:
      title: ShopSitePmsIntegration
      type: object
      additionalProperties: false
      required:
        - async
        - enabled
        - charge_to_room_enabled
        - type
      properties:
        async:
          type: boolean
          nullable: true
        enabled:
          type: boolean
        charge_to_room_enabled:
          type: boolean
        supports_partial_charge_to_room:
          type: boolean
          description: |
            Whether the site's PMS integration supports charging an amount
            less than the outstanding basket total to a room.
        type:
          type: string
          nullable: true
    ShopSiteShopConfig:
      title: ShopSiteShopConfig
      type: object
      additionalProperties: false
      required:
        - features
        - require_member_guests
        - separate_name_values_enforced
      properties:
        features:
          type: array
          items:
            type: object
            additionalProperties: false
        require_member_guests:
          type: boolean
        separate_name_values_enforced:
          type: boolean
    ShopSiteVouchersIntegration:
      title: ShopSiteVouchersIntegration
      type: object
      additionalProperties: false
      required:
        - enabled
        - name
        - type
      properties:
        enabled:
          type: boolean
        name:
          type: string
          nullable: true
        type:
          type: string
          nullable: true
    OrganisationSummary:
      title: OrganisationSummary
      type: object
      additionalProperties: false
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          description: The name of the organisation
          example: Palm Tree Holdings Ltd.
    ShopSite:
      title: ShopSite
      type: object
      description: The shop-domain projection of a `Site` — extends the core `Site` with checkout-facing configuration such as currency, supported payment types, email/SMS branding, feature flags and category mappings. This is the shape used by booking flows, the kiosk and the customer-facing storefront.
      additionalProperties: false
      required:
        - id
        - appointment_enquiries_enabled
        - basket_confirmed_email_message
        - brand_id
        - category_ids
        - country_code
        - country_name
        - currency
        - custom_payment_types
        - email_from_address
        - email_from_address_verified_at
        - email_settings
        - feature_flags
        - features
        - has_booking_engine_integration
        - has_fiscalisation_integration
        - has_payments_integration
        - has_pos_integration
        - has_table_reservation_integration
        - intake_form_questionnaire_id
        - locale
        - name
        - opening_hours
        - pms_integration
        - privacy_policy
        - revenue_centres
        - scheduling_week_interval
        - scheduling_week_interval_start
        - shop_config
        - stripe_config
        - timezone
        - vouchers_integration
        - default_commission_package_id
        - organisation
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the site
        appointment_enquiries_enabled:
          type: boolean
        basket_confirmed_email_message:
          type: string
          nullable: true
          description: |
            A message which is appended to the end of every Basket Confirmed email for this site.

            HTML is supported, however only the following tags are allowed: `h1`, `strong`, `a`, `p`, `br`.
          example: |
            <p>We look forward to seeing you. If anything changes,
            <a href="mailto:hello@example.com">get in touch</a>.</p>
        brand_id:
          type: string
          format: uuid
          description: The ID of the parent `Brand`.
        category_ids:
          type: array
          items:
            type: string
        country_code:
          type: string
          description: The country code of the site
          example: GB
          nullable: true
        country_name:
          type: string
          nullable: true
        currency:
          type: string
          description: The currency of the site. See [Supported Currencies](/endpoints/Meta#listMetaSupportedCurrencies) for a list of supported currencies.
          example: GBP
        custom_payment_types:
          type: array
          items:
            $ref: '#/components/schemas/ShopSiteCustomPaymentType'
        customer_search_config:
          $ref: '#/components/schemas/ShopSiteCustomerSearchConfig'
        email_from_address:
          type: string
          nullable: true
          description: |
            The email address used as the `From` header on all customer-
            facing email this site sends (confirmations, reminders, receipts).
            Must be verified with the email provider before delivery succeeds
            — check `email_from_address_verified_at`.
          example: spa@example.com
        email_from_address_verified_at:
          type: string
          format: date-time
          nullable: true
        email_settings:
          $ref: '#/components/schemas/ShopSiteEmailSettings'
        external_id:
          type: string
          description: |
            An external ID for the site
            This can be used to link the site to an external system.
        feature_flags:
          title: ShopSiteFeatureFlags
          type: object
          additionalProperties:
            type: boolean
        features:
          $ref: '#/components/schemas/ShopSiteFeatures'
        has_booking_engine_integration:
          type: boolean
        has_fiscalisation_integration:
          type: boolean
        has_payments_integration:
          type: boolean
        has_pos_integration:
          type: boolean
        has_table_reservation_integration:
          type: boolean
        intake_form_questionnaire_id:
          type: string
          nullable: true
          description: |
            ID of the intake-form questionnaire applied to bookings at this
            site. Null means no questionnaire is attached and the intake step
            is skipped.
          example: 5f1234567890abcdef123456
        locale:
          type: string
          description: The locale of the site. See [Supported Locales](/endpoints/Meta#listMetaSupportedLocales) for a list of supported locales.
          example: en
        name:
          type: string
          description: |
            Display name of the site, shown to customers in the storefront,
            on receipts, and in confirmation emails sent to guests.
            Trimmed; 1-120 characters and must not contain HTML.
          example: Palm Tree Spa
        opening_hours:
          type: array
          items:
            $ref: '#/components/schemas/ShopSiteOpeningHour'
        payment_config:
          $ref: '#/components/schemas/ShopSitePaymentConfig'
        pms_integration:
          $ref: '#/components/schemas/ShopSitePmsIntegration'
        privacy_policy:
          type: string
          nullable: true
          description: |
            Customer-facing privacy policy shown during checkout and on
            receipts. Markdown is rendered; null means inherit from the
            organisation.
          example: |
            We process your personal data in accordance with GDPR. See our full
            privacy notice at https://example.com/privacy.
        revenue_centres:
          type: array
          items:
            type: object
            additionalProperties:
              title: SiteRevenueCentre
              type: object
              additionalProperties: false
              required:
                - id
                - name
              properties:
                id:
                  type: string
                name:
                  type: string
                tax_configuration_id:
                  type: string
                  nullable: true
                tax_percent:
                  type: integer
        scheduling_week_interval:
          type: integer
          nullable: true
          description: |
            Number of weeks between repeating scheduling rotations. Used to
            roll fortnightly or multi-week rotas. `2` means alternating weeks;
            null means no rotation (every week is identical).
          example: 2
        scheduling_week_interval_start:
          type: string
          format: date-time
          nullable: true
          description: |
            Anchor datetime used to compute which week of a multi-week
            rotation any given date falls into. Paired with
            `scheduling_week_interval`; null disables the rotation.
          example: '2026-01-05T00:00:00Z'
        shop_config:
          $ref: '#/components/schemas/ShopSiteShopConfig'
        stripe_config:
          $ref: '#/components/schemas/ShopSiteStripeConfig'
        terms:
          type: string
          nullable: true
          description: |
            Customer-facing terms and conditions shown at checkout and linked
            in confirmation emails. Markdown is rendered; null means inherit
            from the organisation.
          example: |
            Bookings are subject to our cancellation policy. Full terms at
            https://example.com/terms.
        timezone:
          type: string
          description: The timezone of the site
          example: Europe/London
        vouchers_integration:
          $ref: '#/components/schemas/ShopSiteVouchersIntegration'
        default_commission_package_id:
          type: string
          format: mongo-id
          description: |
            The default commission package for the site. This will be used as the default for any new practitioners, but can be overridden on a per-practitioner basis.
          nullable: true
        organisation:
          $ref: '#/components/schemas/OrganisationSummary'
    basket_confirmed_email_message:
      type: string
      nullable: true
      description: |
        A message which is appended to the end of every Basket Confirmed email for this site.

        HTML is supported, however only the following tags are allowed: `h1`, `strong`, `a`, `p`, `br`.
      example: |
        <p>We look forward to seeing you. If anything changes,
        <a href="mailto:hello@example.com">get in touch</a>.</p>
    category_ids:
      type: array
      items:
        type: string
    email_from_address:
      type: string
      nullable: true
      description: |
        The email address used as the `From` header on all customer-
        facing email this site sends (confirmations, reminders, receipts).
        Must be verified with the email provider before delivery succeeds
        — check `email_from_address_verified_at`.
      example: spa@example.com
    intake_form_questionnaire_id:
      type: string
      nullable: true
      description: |
        ID of the intake-form questionnaire applied to bookings at this
        site. Null means no questionnaire is attached and the intake step
        is skipped.
      example: 5f1234567890abcdef123456
    ShopSite-properties-name:
      type: string
      description: |
        Display name of the site, shown to customers in the storefront,
        on receipts, and in confirmation emails sent to guests.
        Trimmed; 1-120 characters and must not contain HTML.
      example: Palm Tree Spa
    opening_hours:
      type: array
      items:
        $ref: '#/components/schemas/ShopSiteOpeningHour'
    privacy_policy:
      type: string
      nullable: true
      description: |
        Customer-facing privacy policy shown during checkout and on
        receipts. Markdown is rendered; null means inherit from the
        organisation.
      example: |
        We process your personal data in accordance with GDPR. See our full
        privacy notice at https://example.com/privacy.
    scheduling_week_interval:
      type: integer
      nullable: true
      description: |
        Number of weeks between repeating scheduling rotations. Used to
        roll fortnightly or multi-week rotas. `2` means alternating weeks;
        null means no rotation (every week is identical).
      example: 2
    scheduling_week_interval_start:
      type: string
      format: date-time
      nullable: true
      description: |
        Anchor datetime used to compute which week of a multi-week
        rotation any given date falls into. Paired with
        `scheduling_week_interval`; null disables the rotation.
      example: '2026-01-05T00:00:00Z'
    terms:
      type: string
      nullable: true
      description: |
        Customer-facing terms and conditions shown at checkout and linked
        in confirmation emails. Markdown is rendered; null means inherit
        from the organisation.
      example: |
        Bookings are subject to our cancellation policy. Full terms at
        https://example.com/terms.
    default_commission_package_id:
      type: string
      format: mongo-id
      description: |
        The default commission package for the site. This will be used as the default for any new practitioners, but can be overridden on a per-practitioner basis.
      nullable: true
    UpdateShopSite:
      title: UpdateShopSite
      description: Contains properties that may be updated on a `ShopSite`.
      type: object
      additionalProperties: false
      properties:
        basket_confirmed_email_message:
          $ref: '#/components/schemas/basket_confirmed_email_message'
        category_ids:
          $ref: '#/components/schemas/category_ids'
        custom_payment_type_ids:
          type: array
          description: An array of custom payment type IDs for the site
          items:
            type: string
            example: 5f8d944e79c9f341846e807a
        email_from_address:
          $ref: '#/components/schemas/email_from_address'
        email_settings:
          $ref: '#/components/schemas/ShopSiteEmailSettings'
        intake_form_questionnaire_id:
          $ref: '#/components/schemas/intake_form_questionnaire_id'
        name:
          $ref: '#/components/schemas/ShopSite-properties-name'
        opening_hours:
          $ref: '#/components/schemas/opening_hours'
        privacy_policy:
          $ref: '#/components/schemas/privacy_policy'
        scheduling_week_interval:
          $ref: '#/components/schemas/scheduling_week_interval'
        scheduling_week_interval_start:
          $ref: '#/components/schemas/scheduling_week_interval_start'
        terms:
          $ref: '#/components/schemas/terms'
        default_commission_package_id:
          $ref: '#/components/schemas/default_commission_package_id'
    AppointmentEnquirySettings:
      type: object
      description: Properties to be updated in a site's appointment enquiry settings
      title: AppointmentEnquirySettings
      additionalProperties: false
      properties:
        enabled:
          type: boolean
          description: Whether appointment enquiries are enabled for this site.
        min_advance_bookings_interval:
          type: string
          nullable: true
          description: The minimum time before an appointment's start time that an enquiry may be made, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2D
        automatically_confirm:
          type: boolean
          description: Whether enquiries should automatically be confirmed when there is availability.
        automatically_charge:
          type: boolean
          description: Whether enquiries should automatically be charged when being confirmed.
      required:
        - enabled
        - min_advance_bookings_interval
        - automatically_confirm
        - automatically_charge
    UpdateAppointmentEnquirySettings:
      type: object
      description: Properties to be updated in a site's appointment enquiry settings
      title: UpdateAppointmentEnquirySettings
      additionalProperties: false
      properties:
        enabled:
          type: boolean
          description: Whether appointment enquiries are enabled for this site.
        min_advance_bookings_interval:
          type: string
          nullable: true
          description: The minimum time before an appointment's start time that an enquiry may be made, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P2D
        automatically_confirm:
          type: boolean
          description: Whether enquiries should automatically be confirmed when there is availability.
        automatically_charge:
          type: boolean
          description: Whether enquiries should automatically be charged when being confirmed.
    date_from:
      type: string
      format: date
      description: The start of the rule period.
      example: '2021-02-15'
    date_to:
      type: string
      format: date
      description: The end of the rule period.
      example: '2021-02-15'
    is_available:
      type: boolean
      description: Whether the resource is available during this period. Any `false` rules will override `true` rules.
    time_from:
      type: string
      description: The daily start time of the time period, in 24 hour format.
      example: '11:00'
    time_to:
      type: string
      description: The daily end time of the time period, in 24 hour format.
      example: '17:00'
    TaxConfigurationSummary:
      type: object
      title: TaxConfigurationSummary
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the tax configuration.
        name:
          type: string
          description: The name of the tax configuration.
          example: UK VAT
    RevenueCentre:
      type: object
      title: RevenueCentre
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the revenue centre.
          example: spa
        key:
          type: string
          description: The key for the revenue centre (an alias for its ID).
          example: spa
        name:
          type: string
          description: |
            Display name of the revenue centre, shown in the admin UI and
            on financial reports. Revenue centres group sales for tax and
            accounting (e.g. Spa, Retail, Food & Beverage).
            1-120 characters.
          example: Spa
        tax_percent:
          type: number
          description: The percentage of tax to be applied for this revenue centre.
          example: 20
          nullable: true
        tax_configuration:
          $ref: '#/components/schemas/TaxConfigurationSummary'
          nullable: true
        is_required:
          type: boolean
          description: Whether this is a required Trybe revenue revenue centre.
      required:
        - id
        - key
        - name
        - tax_percent
        - tax_configuration
        - is_required
    key:
      type: string
      description: The key for the revenue centre (an alias for its ID).
      example: spa
    RevenueCentre-properties-name:
      type: string
      description: |
        Display name of the revenue centre, shown in the admin UI and
        on financial reports. Revenue centres group sales for tax and
        accounting (e.g. Spa, Retail, Food & Beverage).
        1-120 characters.
      example: Spa
    tax_percent:
      type: number
      description: The percentage of tax to be applied for this revenue centre.
      example: 20
      nullable: true
    CreateRevenueCentre:
      type: object
      title: CreateRevenueCentre
      additionalProperties: false
      properties:
        key:
          $ref: '#/components/schemas/key'
        name:
          $ref: '#/components/schemas/RevenueCentre-properties-name'
        tax_percent:
          $ref: '#/components/schemas/tax_percent'
        tax_configuration_id:
          type: string
          format: mongo-id
          description: |
            Identifier of the tax configuration to apply to sales recorded
            against this revenue centre. The configuration controls the
            tax rate breakdown shown on receipts and reports; the
            configuration must belong to the same site.
      required:
        - name
    tax_configuration_id:
      type: string
      format: mongo-id
      description: |
        Identifier of the tax configuration to apply to sales recorded
        against this revenue centre. The configuration controls the
        tax rate breakdown shown on receipts and reports; the
        configuration must belong to the same site.
    UpdateRevenueCentre:
      type: object
      title: UpdateRevenueCentre
      additionalProperties: false
      properties:
        key:
          $ref: '#/components/schemas/key'
        name:
          $ref: '#/components/schemas/RevenueCentre-properties-name'
        tax_percent:
          $ref: '#/components/schemas/tax_percent'
        tax_configuration_id:
          $ref: '#/components/schemas/tax_configuration_id'
    ExitGratuityOfferingSettings:
      type: object
      description: Settings for exit gratuity to be applied to specific offerings.
      title: ExitGratuityOfferingSettings
      additionalProperties: false
      properties:
        no_tip_exit_behaviour:
          type: string
          description: The behavior to apply when a customer exits through a gate and does not select a tip option for these offerings.
          nullable: true
          enum:
            - allow_exit
            - disallow_exit
        tip_wording:
          type: string
          description: Custom wording to use for the tip option when a customer exits through a gate for these offerings. If not provided, a default wording will be used.
          nullable: true
          example: Add a gratuity for your therapist
        percentages:
          type: array
          description: The percentage options to be presented to customers when exiting through a gate for these offerings
          items:
            type: number
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
      required:
        - no_tip_exit_behaviour
        - tip_wording
        - offerings
        - percentages
    ServiceChargeOfferingSettings:
      type: object
      description: Properties in a site's service charge settings
      title: ServiceChargeOfferingSettings
      additionalProperties: false
      properties:
        percentage:
          type: number
          description: The percentage service charge to be applied, to the nearest half percent
          example: 12.5
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
      required:
        - percentage
        - offerings
    ServiceChargeSettings:
      type: object
      description: Properties to be updated in a site's service charge settings
      title: ServiceChargeSettings
      additionalProperties: false
      properties:
        default_percentage:
          type: number
          description: The percentage service charge to be applied, to the nearest half percent
          example: 10
        exit_gratuity_percentages:
          type: array
          description: The percentage options to be presented to customers when exiting through a gate
          items:
            type: number
        exit_gratuity_offering_defaults:
          type: array
          items:
            $ref: '#/components/schemas/ExitGratuityOfferingSettings'
        tip_on_terminal_enabled:
          type: boolean
          description: Whether to support adding a tip from card reader payments.
        tip_on_exit_gate:
          type: string
          description: Whether to support adding a tip when a customer exits through a gate.
          nullable: true
          enum:
            - ask_lead_booker
            - ask_each_guest
        allow_exit_voucher_balance_consumption:
          type: boolean
          nullable: true
          description: Whether exit gratuity should be consumed from gift voucher first.
          example: false
        offering_defaults:
          type: array
          items:
            $ref: '#/components/schemas/ServiceChargeOfferingSettings'
        no_tip_exit_behaviour:
          type: string
          description: The behavior to apply when a customer exits through a gate and does not select a tip option for these offerings.
          nullable: true
          enum:
            - allow_exit
            - disallow_exit
        tip_wording:
          type: string
          description: Custom wording to use for the tip option when a customer exits through a gate for these offerings. If not provided, a default wording will be used.
          nullable: true
          example: Add a gratuity for your therapist
      required:
        - tip_on_terminal_enabled
        - tip_on_exit_gate
        - default_percentage
        - exit_gratuity_percentages
        - allow_exit_voucher_balance_consumption
        - offering_defaults
        - no_tip_exit_behaviour
        - tip_wording
    UpdateExitGratuityOfferingSettings:
      type: object
      description: Settings for exit gratuity to be applied to specific offerings.
      title: UpdateExitGratuityOfferingSettings
      additionalProperties: false
      properties:
        no_tip_exit_behaviour:
          type: string
          description: The behavior to apply when a customer exits through a gate and does not select a tip option for these offerings.
          nullable: true
          enum:
            - allow_exit
            - disallow_exit
        tip_wording:
          type: string
          description: Custom wording to use for the tip option when a customer exits through a gate for these offerings. If not provided, a default wording will be used.
          nullable: true
          example: Add a gratuity for your therapist
        percentages:
          type: array
          description: The percentage options to be presented to customers when exiting through a gate for these offerings
          items:
            type: number
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifierRequest'
      required:
        - no_tip_exit_behaviour
        - tip_wording
        - offerings
        - percentages
    UpdateServiceChargeOfferingSettings:
      type: object
      description: Settings for service charge to be applied to specific offerings.
      title: UpdateServiceChargeOfferingSettings
      additionalProperties: false
      properties:
        percentage:
          type: number
          description: The percentage service charge to be applied, to the nearest half percent
          example: 12.5
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/OfferingIdentifierRequest'
      required:
        - percentage
        - offerings
    UpdateServiceChargeSettings:
      type: object
      description: Properties to be updated in a site's service charge settings
      title: UpdateServiceChargeSettings
      additionalProperties: false
      properties:
        default_percentage:
          type: number
          description: The percentage service charge to be applied, to the nearest half percent
          example: 10
        exit_gratuity_percentages:
          type: array
          description: The percentage options to be presented to customers when exiting through a gate
          items:
            type: number
        exit_gratuity_offering_defaults:
          type: array
          items:
            $ref: '#/components/schemas/UpdateExitGratuityOfferingSettings'
        tip_on_terminal_enabled:
          type: boolean
          description: Whether to support adding a tip from card reader payments.
        tip_on_exit_gate:
          type: string
          description: Whether to support adding a tip when a customer exits through a gate.
          nullable: true
          enum:
            - ask_lead_booker
            - ask_each_guest
        allow_exit_voucher_balance_consumption:
          type: boolean
          nullable: true
          description: Whether exit gratuity should be consumed from gift voucher first.
          example: false
        no_tip_exit_behaviour:
          type: string
          description: The behavior to apply when a customer exits through a gate and does not select a tip option for these offerings.
          nullable: true
          enum:
            - allow_exit
            - disallow_exit
        tip_wording:
          type: string
          description: Custom wording to use for the tip option when a customer exits through a gate for these offerings. If not provided, a default wording will be used.
          nullable: true
          example: Add a gratuity for your therapist
        offering_defaults:
          type: array
          items:
            $ref: '#/components/schemas/UpdateServiceChargeOfferingSettings'
    AutoCheckoutSettings:
      type: object
      description: Properties to be updated in a site's auto checkout settings
      title: AutoCheckoutSettings
      additionalProperties: false
      properties:
        checkout_sessions_enabled:
          type: boolean
          description: Whether to support automation of checking out all sessions from the previous day.
      required:
        - checkout_sessions_enabled
    UpdateAutoCheckoutSettings:
      type: object
      description: Properties to be updated in a site's auto checkout settings
      title: UpdateAutoCheckoutSettings
      additionalProperties: false
      properties:
        checkout_sessions_enabled:
          type: boolean
          description: Whether to support automation of checking out all sessions from the previous day.
    SmsNotificationSettings:
      title: SmsNotificationSettings
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the SMS Notification Settings.
        confirmation_sms_enabled:
          type: boolean
          description: |
            Whether the order confirmation SMS is enabled.
          example: false
        automated_confirmation_sms_enabled:
          type: boolean
          description: |
            Whether the order confirmation SMS has automation turned off or not.
          example: false
        cancellation_sms_enabled:
          type: boolean
          description: |
            Whether the order cancellation SMS is enabled.
          example: false
        pay_by_link_sms_enabled:
          type: boolean
          description: |
            Whether the pay by link request SMS is enabled.
          example: false
        billing_details_request_sms_enabled:
          type: boolean
          description: |
            Whether the billing details request SMS for memberships is enabled.
          example: false
        waitlist_confirmation_sms_enabled:
          type: boolean
          description: |
            Whether the waitlist update SMS is enabled.
          example: false
        reminder_sms_enabled:
          type: boolean
          description: |
            Whether the reminder SMS is enabled.
          example: false
        automated_reminder_sms_enabled:
          type: boolean
          description: |
            Whether the order reminder SMS has automation turned off or not.
          example: false
        reminder_sms_time:
          type: string
          format: time
          description: |
            The time of day the reminder SMS will be sent for automated messages.
        reminder_sms_days_ahead:
          type: integer
          description: |
            The number of days ahead of the booking the reminder SMS will be sent for automated messages.
          example: 3
        follow_up_sms_enabled:
          type: boolean
          description: |
            Whether the follow up SMS is enabled.
          example: false
        automated_follow_up_sms_enabled:
          type: boolean
          description: |
            Whether the order follow up SMS has automation turned off or not.
          example: false
        follow_up_sms_time:
          type: string
          format: time
          description: |
            The time of day the follow up SMS will be sent for automated messages.
        follow_up_sms_days_after:
          type: integer
          description: |
            The number of days after the booking the follow up SMS will be sent for automated messages.
          example: 3
        sid:
          type: string
          description: |
            The sender identifier registered with the SMS gateway. For Twilio this is the alphanumeric sender ID or Messaging Service SID; recipients see it as the "from" name on the text. Country restrictions on alphanumeric sender IDs apply.
          example: SENDERSPA
        provider:
          type: string
          description: |
            Which SMS gateway sends outbound texts for this site. Only `twilio` is supported today; new sites should leave this at the default and configure Twilio credentials separately in the integrations section.
          example: twilio
        from_number:
          type: string
          description: |
            The phone number the SMS will be sent from.
          example: 1234567890
        confirmation_sms_offerings:
          type: array
          nullable: true
          description: |
            The offerings that automated confirmation texts are sent for. If empty, confirmation texts are sent for all offerings.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        reminder_sms_offerings:
          type: array
          nullable: true
          description: |
            The offerings that automated reminder texts are sent for. If empty, reminder texts are sent for all offerings.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        follow_up_sms_offerings:
          type: array
          nullable: true
          description: |
            The offerings that automated follow up texts are sent for. If empty, follow up texts are sent for all offerings.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
      required:
        - id
        - confirmation_sms_enabled
        - automated_confirmation_sms_enabled
        - cancellation_sms_enabled
        - pay_by_link_sms_enabled
        - billing_details_request_sms_enabled
        - waitlist_confirmation_sms_enabled
        - reminder_sms_enabled
        - automated_reminder_sms_enabled
        - reminder_sms_time
        - reminder_sms_days_ahead
        - follow_up_sms_enabled
        - automated_follow_up_sms_enabled
        - follow_up_sms_time
        - follow_up_sms_days_after
        - sid
        - provider
        - from_number
    SiteLegalLocaleStrings:
      title: SiteLegalLocaleStrings
      type: object
      additionalProperties: false
      properties:
        terms:
          type: string
          nullable: true
          description: The localised terms and conditions for the site in the given locale.
        privacy_policy:
          type: string
          nullable: true
          description: The localised privacy policy for the site in the given locale.
      required:
        - terms
        - privacy_policy
    SiteFeatures:
      title: SiteFeatures
      type: object
      additionalProperties: false
      properties:
        support_wearable_payments:
          type: boolean
          description: Whether the site supports wearable payments
        support_terminal_initiated_payments:
          type: boolean
          description: Whether the site supports terminal initiated payments
        terminal_payment_retail_product_id:
          type: string
          format: object-id
          description: The ID of the retail product which a terminal payment can be taken for
          nullable: true
      required:
        - support_wearable_payments
        - support_terminal_initiated_payments
        - terminal_payment_retail_product_id
    OfferingSearchResult:
      title: OfferingSearchResult
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the offering.
        offering_type:
          type: string
          description: The type of the offering.
          example: area_booking
        name:
          type: string
          description: The name of the offering.
          example: Hot Tub Booking
        members_only:
          type: boolean
          description: Whether the offering is only available to members.
          example: true
        image_url:
          type: string
          description: A URL for an image representing the offering.
          example: https://example.com/image.jpg
      required:
        - id
        - offering_type
        - name
        - members_only
        - image_url
    SsoConfig:
      type: object
      title: SsoConfig
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the SSO configuration.
        site_id:
          type: string
          format: uuid
          description: The ID of the site.
        type:
          type: string
          description: The type of SSO configuration.
          example: customer_sso
        enabled:
          type: boolean
          description: Whether the SSO configuration is enabled.
          example: true
        authorize_url:
          type: string
          description: The URL to redirect to for authorization.
          example: https://api.trybe.test/authorize
        credentials:
          type: object
          title: SsoCredentials
          description: |
            The encrypted credentials required for the SSO configuration.
          additionalProperties: false
          properties:
            client_id:
              type: string
              description: The client ID for the SSO configuration.
              example: '1234'
            has_client_secret:
              type: boolean
              description: Whether the SSO configuration has a client secret.
              example: true
            masked_client_secret:
              type: string
              description: The masked client secret for the SSO configuration.
              example: '***********'
            additional_authorize_query_params:
              type: array
              description: Additional query parameters to include in the authorization request.
              items:
                type: object
                title: SsoAdditionalAuthorizeQueryParams
                additionalProperties: false
                properties:
                  key:
                    type: string
                    description: The key of the additional query parameter.
                  value:
                    type: string
                    description: The value of the additional query parameter.
            additional_token_query_params:
              type: array
              description: Additional query parameters to include in the token request.
              items:
                type: object
                title: SsoAdditionalTokenQueryParams
                additionalProperties: false
                properties:
                  key:
                    type: string
                    description: The key of the additional query parameter.
                  value:
                    type: string
                    description: The value of the additional query parameter.
        token_url:
          type: string
          description: The URL to request an access token.
          example: https://api.trybe.test/token
        user_info_url:
          type: string
          description: The URL to request user information.
          example: https://api.trybe.test/userinfo
        scopes:
          type: array
          description: The scopes to request during authorization.
          items:
            type: string
            example: openid
        include_existing_url_params:
          type: boolean
          description: Whether to include existing URL parameters in the authorization request.
          example: false
        token_request_style:
          type: string
          description: The style of the token request.
          example: form_params
          enum:
            - form_params
            - json
        user_mappings:
          type: array
          description: Mappings of user information fields.
          items:
            type: object
            title: SsoUserMapping
            additionalProperties: false
            properties:
              key:
                type: string
                description: The key of the user information field.
                example: email
              fields:
                type: array
                description: The fields to map to the user information field.
                items:
                  type: string
                  example: email
        created_at:
          type: string
          format: date-time
          description: The date and time when the SSO configuration was created.
          example: '2025-05-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time when the SSO configuration was last updated.
          example: '2025-05-01T00:00:00Z'
      required:
        - id
        - site_id
        - type
        - enabled
        - authorize_url
        - credentials
        - token_url
        - user_info_url
        - scopes
        - created_at
        - updated_at
    SoldByUser:
      title: SoldByUser
      type: object
      additionalProperties: false
      description: |
        An entity that can be attributed as the "sold by" party on an
        `Order` or `OrderLine`. Sold-by entities are either Trybe users
        (typically front-of-house staff that took the sale) or
        `Practitioner`s (typically the therapist that delivered the
        service).
      properties:
        id:
          type: string
          format: uuid
          description: |
            The ID of the underlying user or practitioner. Use this as the
            `sold_by` value when creating or updating orders, baskets, or
            order lines.
          example: 5f8d944e79c9f341846e807a
        name:
          type: string
          description: |
            Display name for the entity. For users this is the
            concatenated first and last name; for practitioners it is the
            practitioner record's `name`.
          example: Ada Lovelace
        type:
          type: string
          enum:
            - user
            - practitioner
            - ''
          description: |
            Discriminator indicating which underlying entity the row
            represents. An empty string is returned when the underlying
            model does not declare a type.
          example: practitioner
      required:
        - id
        - name
        - type
    MessageFragment:
      title: MessageFragment
      type: object
      additionalProperties: false
      description: |
        A `MessageFragment` is a reusable block of HTML/Markdown content
        that is concatenated into transactional emails (booking
        confirmations, reminders, follow-ups, etc.). Fragments are scoped
        to a site, can be filtered by `message_type`, and can be limited
        to specific offerings or membership types so that copy is
        tailored to the customer's context.

        At send time, the messaging pipeline pulls every fragment whose
        `message_type` matches the message being sent and whose
        `offerings` and `permitted_membership_type_ids` filters are
        satisfied, sorts them by ascending `priority`, and renders them
        inline into the email body.
      properties:
        id:
          type: string
          format: mongo-id
          description: Unique identifier of the message fragment.
          example: 65d4a6f7f4c1b22a3c5d4e8a
        name:
          type: string
          description: |
            Internal label for the fragment, shown in the admin UI when
            authoring email templates. Not visible to customers.
          example: Spa - arrival instructions
        message_type:
          type: string
          description: |
            Which transactional email this fragment is included in.
            Fragments are only rendered into the matching message type.
          enum:
            - basket_cancelled
            - basket_confirmed
            - basket_follow_up
            - basket_item_cancelled
            - basket_reminder
            - order_summary
            - pay_by_link_request
            - appointment_enquiry_confirmed
            - visit_prompt
            - membership_welcome
            - membership_cancelled
            - voucher_recipient
            - membership_enquiry_confirmed
            - new_order
            - new_enquiry
          example: basket_confirmed
        message:
          type: string
          nullable: true
          description: |
            The body of the fragment. Accepts a restricted subset of HTML
            (basic block and inline tags) which is sanitised on save.
            Liquid-style placeholders such as `{{ customer.first_name }}`
            and `{{ booking.starts_at }}` are interpolated when the email
            is rendered.
          example: |
            <p>Hi {{ customer.first_name }} - we're looking forward to
            seeing you on {{ booking.starts_at|date }}. Please arrive
            15 minutes early to check in at reception.</p>
        priority:
          type: integer
          nullable: true
          description: |
            Render order within a message. Fragments are concatenated in
            ascending `priority` order, so lower numbers appear earlier
            in the email body. Use to control which paragraph leads.
          example: 10
        offerings:
          type: array
          description: |
            Offerings this fragment applies to. When empty, the fragment
            applies to every offering at the site (a global fallback).
            When non-empty, the fragment is only included if the
            message's booking contains at least one matching offering.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        permitted_membership_type_ids:
          type: array
          nullable: true
          description: |
            Optional list of `MembershipType` IDs. When set, the fragment
            is only rendered for customers who hold an active membership
            of one of these types - useful for member-only welcome copy,
            loyalty perks, or upgrade prompts. Empty/null means no
            membership filter applies.
          items:
            type: string
            format: mongo-id
          example:
            - 65a1c4f7f4c1b22a3c5d1234
        site_id:
          type: string
          format: uuid
          description: |
            Site the fragment belongs to. Fragments are authored
            per-site so each location can tailor its email copy.
        organisation_id:
          type: string
          format: uuid
          description: Organisation that owns the site.
      required:
        - id
        - name
        - message_type
        - message
        - priority
        - offerings
        - permitted_membership_type_ids
        - site_id
        - organisation_id
    MessageFragmentLocaleStrings:
      title: MessageFragmentLocaleStrings
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
          description: The localised name for this message fragment in the given locale.
          example: Spa - arrival instructions
        message:
          type: string
          nullable: true
          description: The localised message body for this message fragment in the given locale.
          example: <p>Welcome to our spa. Please arrive 15 minutes early to check in.</p>
      required:
        - name
        - message
    SmsFragment:
      title: SmsFragment
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the SMS Fragment.
        name:
          type: string
          description: The name of the SMS Fragment.
          example: Order Confirmation
        message_type:
          type: string
          description: The type of message the SMS Fragment applies to.
          enum:
            - basket_confirmed
            - basket_cancelled_with_charge
            - basket_cancelled_without_charge
            - basket_reminder
            - basket_follow_up
            - pay_by_link_request
            - billing_details_request
        message:
          type: string
          description: The contents of the SMS Fragment.
          example: |
            Hi! Your order has been confirmed. We look forward to seeing you on Saturday 20th January at 12pm.
        priority:
          type: integer
          description: The priority of the SMS Fragment. Fragments will be added to messages in ascending order.
          example: 10
        offerings:
          type: array
          description: |
            An array of offerings which the SMS Fragment applies to. If empty, the SMS Fragment applies to no offerings.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        site_id:
          type: string
          format: uuid
          description: The ID of the site the SMS Fragment is associated with.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the SMS Fragment is associated with.
      required:
        - id
        - name
        - message_type
        - message
        - priority
        - offerings
        - site_id
        - organisation_id
    ListAppointmentEnquiriesResponse:
      title: ListAppointmentEnquiriesResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AppointmentEnquiry'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    ReportFilter:
      title: ReportFilter
      type: object
      additionalProperties: false
      properties:
        key:
          type: string
          description: The query parameter this filter relates to.
          example: date_from
        type:
          type: string
          description: The type of the value for this filter.
          example: string
          enum:
            - boolean
            - date
            - string
        string_value:
          type: string
          description: The value of this filter, if the value is a string.
          example: confirmed
        date_value:
          type: string
          format: date-time
          description: The value of this filter, if the value is a date.
        boolean_value:
          type: boolean
          description: The value of this filter, if the value is a boolean.
      required:
        - key
        - type
    SmartFilter:
      title: SmartFilter
      type: object
      additionalProperties: false
      properties:
        key:
          type: string
          description: A key representing the smart filter.
          example: recently_created
        name:
          type: string
          description: A name for the smart filter.
          example: Recently created
        count:
          type: integer
          description: The number of results matching this smart filter.
          example: 12
        filters:
          type: array
          description: An array of filters to be applied when using this smart filter.
          items:
            $ref: '#/components/schemas/ReportFilter'
      required:
        - key
        - name
        - count
        - filters
    ListClientAssociatedBarcodesResponse:
      title: ListClientAssociatedBarcodesResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AssociatedBarcode'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    ListLedgerLinesResponse:
      title: ListLedgerLinesResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/LedgerLine'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    PayoutSummary:
      type: object
      title: PayoutSummary
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the payout.
        status:
          type: string
          description: The status of the payout.
        payout_date:
          type: string
          format: date
          description: The date that the payout will be processed.
        processed_date:
          type: string
          nullable: true
          format: date-time
          description: The date and time that the payout was processed.
        num_charges:
          type: integer
          description: The number of charges included in this payout.
        amount:
          type: string
          description: The total amount of money included in this payout.
        currency:
          type: string
          description: The currency code of this payout.
    ListPayoutsResponse:
      title: ListPayoutsResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PayoutSummary'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    PractitionerOccupancyItem:
      title: PractitionerOccupancyItem
      additionalProperties: false
      type: object
      required:
        - practitioner
        - bookable_mins
        - blocked_mins
        - appointment_mins
        - session_mins
      properties:
        practitioner:
          $ref: '#/components/schemas/PractitionerSummary'
        bookable_mins:
          type: integer
          description: Total bookable (available) minutes for the practitioner in the period.
          example: 2400
        blocked_mins:
          type: integer
          description: Total blocked minutes for the practitioner in the period.
          example: 120
        appointment_mins:
          type: integer
          description: Total appointment minutes for the practitioner in the period.
          example: 1800
        session_mins:
          type: integer
          description: Total session minutes for the practitioner in the period.
          example: 300
    PractitionerOccupancyTotals:
      title: PractitionerOccupancyTotals
      additionalProperties: false
      type: object
      description: Aggregated totals across all practitioners in the report.
      required:
        - bookable_mins
        - blocked_mins
        - appointment_mins
        - session_mins
      properties:
        bookable_mins:
          type: integer
          description: Total bookable minutes across all practitioners.
          example: 9600
        blocked_mins:
          type: integer
          description: Total blocked minutes across all practitioners.
          example: 480
        appointment_mins:
          type: integer
          description: Total appointment minutes across all practitioners.
          example: 7200
        session_mins:
          type: integer
          description: Total session minutes across all practitioners.
          example: 1200
    PractitionerOccupancyReport:
      title: PractitionerOccupancyReport
      additionalProperties: false
      type: object
      required:
        - data
        - totals
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerOccupancyItem'
        totals:
          $ref: '#/components/schemas/PractitionerOccupancyTotals'
    PractitionerOccupancyByDateItem:
      title: PractitionerOccupancyByDateItem
      additionalProperties: false
      type: object
      required:
        - date
        - practitioner
        - bookable_mins
        - blocked_mins
        - appointment_mins
        - session_mins
      properties:
        date:
          type: string
          format: date
          description: The date this record represents.
          example: '2024-01-15'
        practitioner:
          $ref: '#/components/schemas/PractitionerSummary'
        bookable_mins:
          type: integer
          description: Total bookable (available) minutes for the practitioner on this date.
          example: 480
        blocked_mins:
          type: integer
          description: Total blocked minutes for the practitioner on this date.
          example: 60
        appointment_mins:
          type: integer
          description: Total appointment minutes for the practitioner on this date.
          example: 360
        session_mins:
          type: integer
          description: Total session minutes for the practitioner on this date.
          example: 60
    PractitionerOccupancyByDateTotals:
      title: PractitionerOccupancyByDateTotals
      additionalProperties: false
      type: object
      description: Aggregated totals across all practitioners and dates in the report.
      required:
        - bookable_mins
        - blocked_mins
        - appointment_mins
        - session_mins
      properties:
        bookable_mins:
          type: integer
          description: Total bookable minutes across all practitioners and dates.
          example: 9600
        blocked_mins:
          type: integer
          description: Total blocked minutes across all practitioners and dates.
          example: 480
        appointment_mins:
          type: integer
          description: Total appointment minutes across all practitioners and dates.
          example: 7200
        session_mins:
          type: integer
          description: Total session minutes across all practitioners and dates.
          example: 1200
    PractitionerOccupancyByDateReport:
      title: PractitionerOccupancyByDateReport
      additionalProperties: false
      type: object
      required:
        - data
        - totals
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerOccupancyByDateItem'
        totals:
          $ref: '#/components/schemas/PractitionerOccupancyByDateTotals'
    UsedPromoCodeSummary:
      type: object
      title: UsedPromoCodeSummary
      additionalProperties: false
      required:
        - currency
        - discount_type_id
        - discount_type_code
        - is_archived
        - site_id
        - total_discount_across_orders
        - total_times_used
      properties:
        discount_type_id:
          type: string
          format: uuid
          description: The ID of the used promo code.
        discount_type_code:
          type: string
          description: The code for the used promo code.
          example: SUMMER23
        total_times_used:
          type: integer
          description: The total number of times the promo code has been used across all orders.
          example: 1120
        total_discount_across_orders:
          type: integer
          description: The total discount across all orders from the used promo code.
          example: 10000
        currency:
          type: string
          description: |
            The currency of the total discount across all orders from the used promo code.
            This is associated with the site.
          example: gbp
        is_archived:
          type: boolean
          description: |
            Whether the used promo code has been archived.
          example: false
        site_id:
          type: string
          format: uuid
          description: The ID of the site the used promo code is associated with.
    UsedPromoCodeBreakdown:
      type: object
      title: UsedPromoCodeBreakdown
      additionalProperties: false
      required:
        - applied_at
        - applied_by
        - currency
        - discount_type_code
        - discount_type_id
        - is_archived
        - order_id
        - order_ref
        - order_total
        - site_id
        - total_discount_on_order
      properties:
        discount_type_id:
          type: string
          format: uuid
          description: The ID of the used promo code.
        discount_type_code:
          type: string
          description: The code for the used promo code.
          example: SUMMER23
        order_id:
          type: string
          format: uuid
          description: The ID of the basket the used promo code was applied to.
        order_ref:
          type: string
          description: The reference of the order the used promo code was applied to.
          example: TRY00
        order_total:
          type: integer
          description: The total value of the order the used promo code was applied to.
          example: 1000
        total_discount_on_order:
          type: integer
          description: The total discount on the order from the used promo code.
          example: 1000
        currency:
          type: string
          description: |
            The currency of the total discount on the order from the used promo code.
            This is associated with the site.
          example: gbp
        applied_by:
          type: object
          description: |
            Information about the user who applied the promo code.
            If this is null, the promo code was applied by the customer.
          $ref: '#/components/schemas/UserSummary'
          nullable: true
        applied_at:
          type: string
          format: date-time
          description: |
            The date and time the promo code was applied.
        is_archived:
          type: boolean
          description: |
            Whether the used promo code has been archived.
          example: false
        site_id:
          type: string
          format: uuid
          description: The ID of the site the used promo code is associated with.
    UsedDiscountTypeSummary:
      type: object
      title: UsedDiscountTypeSummary
      additionalProperties: false
      required:
        - currency
        - discount_type_id
        - discount_type_code
        - is_archived
        - site_id
        - total_discount
        - total_discount_across_items
        - total_discount_across_orders
        - total_times_used_on_items
        - total_times_used_on_orders
      properties:
        discount_type_id:
          type: string
          format: uuid
          description: The ID of the used discount type.
        discount_type_code:
          type: string
          description: The code for the used discount type.
          example: AMT
        total_times_used_on_orders:
          type: integer
          description: The total number of times the discount type has been used across all orders.
          example: 64
        total_times_used_on_items:
          type: integer
          description: The total number of times the discount type has been used across all items.
          example: 20
        total_discount_across_items:
          type: integer
          description: The total discount across all items from the used discount type.
          example: 10000
        total_discount_across_orders:
          type: integer
          description: The total discount across all orders from the used discount type.
          example: 10000
        total_discount:
          type: integer
          description: The total discount across all items and orders from the used discount type.
          example: 20000
        currency:
          type: string
          description: |
            The currency of the total discount across all items and orders from the used discount type.
            This is associated with the site.
          example: gbp
        is_archived:
          type: boolean
          description: |
            Whether the used discount type has been archived.
          example: false
        site_id:
          type: string
          format: uuid
          description: The ID of the site the used discount type is associated with.
    UsedDiscountTypeBreakdown:
      type: object
      title: UsedDiscountTypeBreakdown
      additionalProperties: false
      required:
        - applied_by
        - applied_at
        - currency
        - discount_applied_to_item
        - discount_applied_to_order
        - discount_type_code
        - discount_type_id
        - is_archived
        - order_id
        - order_ref
        - site_id
      properties:
        discount_type_id:
          type: string
          format: uuid
          description: The ID of the used discount type.
        discount_type_code:
          type: string
          description: The code for the used discount type.
          example: AMT
        order_id:
          type: string
          format: uuid
          description: The ID of the basket the used discount type was applied to.
        order_ref:
          type: string
          description: The reference of the order the used discount type was applied to.
          example: TRY00
        discount_applied_to_item:
          type: integer
          description: The discount applied to the item from the used discount type.
          example: 1000
        discount_applied_to_order:
          type: integer
          description: The discount applied to the order from the used discount type.
          example: 1000
        currency:
          type: string
          description: |
            The currency of the total discount on the items and order from the used discount type.
            This is associated with the site.
          example: gbp
        applied_by:
          type: object
          description: |
            Information about the user who applied the discount. 
            If this is null, the discount was applied by the customer.
          $ref: '#/components/schemas/UserSummary'
          nullable: true
        applied_at:
          type: string
          format: date-time
          description: |
            The date and time the discount type was applied.
        is_archived:
          type: boolean
          description: |
            Whether the used discount type has been archived.
          example: false
        site_id:
          type: string
          format: uuid
          description: The ID of the site the used discount type is associated with.
    DepositLedgerBalances:
      type: object
      title: DepositLedgerBalances
      additionalProperties: true
      properties:
        deposit:
          type: integer
          description: The balance of the deposit revenue centre at the date of the report.
          example: 5000
        deposit_redemption:
          type: integer
          description: The balance of the deposit_redemption revenue centre at the date of the report.
          example: 3500
      required:
        - deposit
        - deposit_redemption
    DepositLedgerPayable:
      type: object
      title: DepositLedgerPayable
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the payable model.
        type:
          type: string
          description: The type of the payable model.
          example: basket
        reference:
          type: string
          description: A reference for the payable model.
          example: TRY00
        description:
          type: string
          description: Further details about the payable model
          example: dan@example.com
        ledger_balance:
          type: integer
          description: The balance of the voucher at the date of the report.
          example: 5000
        ledger_balances:
          $ref: '#/components/schemas/DepositLedgerBalances'
      required:
        - id
        - type
        - reference
        - description
        - ledger_balance
        - ledger_balances
    ListDepositLedgerResponse:
      title: ListDepositLedgerResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DepositLedgerPayable'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    DepositLedgerSummary:
      type: object
      title: DepositLedgerSummary
      additionalProperties: false
      properties:
        balances:
          $ref: '#/components/schemas/DepositLedgerBalances'
        balance:
          type: integer
          description: The balance of the deposit ledger at the date of the report.
          example: 5095
      required:
        - balances
        - balance
    DepositLedgerSummaryResponse:
      title: DepositLedgerSummaryResponse
      additionalProperties: false
      type: object
      properties:
        data:
          $ref: '#/components/schemas/DepositLedgerSummary'
      required:
        - data
    VoucherLedgerBalances:
      type: object
      title: VoucherLedgerBalances
      additionalProperties: false
      properties:
        voucher:
          type: integer
          description: The balance of the voucher revenue centre at the date of the report.
          example: 5000
        voucher_difference:
          type: integer
          description: The balance of the voucher_difference revenue centre at the date of the report.
          example: 2000
        voucher_discount:
          type: integer
          description: The balance of the voucher_discount revenue centre at the date of the report.
          example: 0
        voucher_redemption:
          type: integer
          description: The balance of the voucher_redemption revenue centre at the date of the report.
          example: 0
        voided_voucher:
          type: integer
          description: The balance of the voided_voucher revenue centre at the date of the report.
          example: 0
      required:
        - voucher
        - voucher_difference
        - voucher_discount
        - voucher_redemption
        - voided_voucher
    VoucherLedgerVoucher:
      type: object
      title: VoucherLedgerVoucher
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the voucher.
        code:
          type: string
          description: The voucher code.
          example: ABC123XYZ
        valid_from_date:
          type: string
          format: date-time
          description: The date and time the voucher code is valid from.
          example: '2023-04-02T00:00:00+01:00'
        valid_to_date:
          type: string
          format: date-time
          description: The date and time the voucher code is valid to.
          example: '2023-04-02T00:00:00+01:00'
        amount_type:
          type: string
          description: The type of the voucher code.
          enum:
            - cash
            - free_item
        amount:
          type: integer
          description: The face value of the voucher code.
          example: 10000
        balance:
          type: integer
          description: The remaining balance of the voucher code.
          example: 5000
        revenue_amount:
          type: integer
          description: The amount of revenue from the voucher (i.e. what it was sold for).
          example: 8000
        difference_amount:
          type: integer
          description: The difference between the voucher's amount and its revenue amount.
          example: 2000
        ledger_balance:
          type: integer
          description: The balance of the voucher at the date of the report.
          example: 5000
        ledger_balances:
          $ref: '#/components/schemas/VoucherLedgerBalances'
        currency:
          type: string
          description: The currency of the voucher code. See [Supported Currencies](/endpoints/Meta#metaSupportedCurrencies) for a list of supported currencies.
          example: gbp
        partially_redeemable:
          type: boolean
          description: Whether the voucher code is partially redeemable.
        voucher_name:
          type: string
          description: The name of the voucher type.
          example: £100 treatment voucher
      required:
        - id
        - code
        - valid_from_date
        - valid_to_date
        - amount_type
        - amount
        - balance
        - revenue_amount
        - difference_amount
        - ledger_balance
        - ledger_balances
        - currency
        - partially_redeemable
        - voucher_name
    ListVoucherLedgerResponse:
      title: ListVoucherLedgerResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/VoucherLedgerVoucher'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    VoucherLedgerSummary:
      type: object
      title: VoucherLedgerSummary
      additionalProperties: false
      properties:
        balances:
          $ref: '#/components/schemas/VoucherLedgerBalances'
        balance:
          type: integer
          description: The balance of the voucher ledger at the date of the report.
          example: 5000
      required:
        - balances
        - balance
    VoucherLedgerSummaryResponse:
      title: VoucherLedgerSummaryResponse
      additionalProperties: false
      type: object
      properties:
        data:
          $ref: '#/components/schemas/VoucherLedgerSummary'
      required:
        - data
    ServiceChargeItem:
      type: object
      title: ServiceChargeItem
      additionalProperties: false
      properties:
        id:
          description: The ID of the basket item.
          type: string
          format: object-id
        basket_id:
          description: The ID of the basket this item belongs to.
          type: string
          format: object-id
        order_ref:
          description: The order ref of the basket this item belongs to.
          type: string
          example: TRY03
        order_status:
          description: The status of the basket this item belongs to.
          type: string
          example: settled
        revenue_date:
          description: The revenue date of the basket this item belongs to.
          type: string
          format: date
          nullable: true
        item_date:
          description: The date of this item. If the item is a booking this will be the date it takes place.
          type: string
          format: date
          nullable: true
        quantity:
          description: The quantity of this item. This is 1 in the majority of cases.
          type: integer
          example: 1
        offering_id:
          description: The ID of the offering this item is for.
          type: string
          format: object-id
        offering_type:
          description: The type of offering this item is for.
          type: string
          example: appointment
        offering_name:
          description: The name of the offering this item is for.
          type: string
          example: 60 Minute Massage
        total_cost:
          description: The total cost of the item, in minor units.
          type: integer
          nullable: true
          example: 15000
        net_total:
          description: The net total of the item, in minor units.
          type: integer
          nullable: true
          example: 12000
        service_charge:
          description: The amount of service charge associated with the item.
          type: integer
          nullable: true
          example: 1000
        sold_by:
          description: The staff member responsible for selling this item.
          $ref: '#/components/schemas/SoldBy'
          nullable: true
        practitioner:
          description: Details of the practitioners assigned to this item.
          $ref: '#/components/schemas/PractitionerSummary'
        start_time:
          description: The date and time this item's booking starts.
          type: string
          nullable: true
          format: date-time
        sales_channel:
          description: The sales channel of the order.
          type: string
          nullable: true
          example: Website
        payment_methods:
          description: A comma-separated list of payment methods used for this item's basket.
          type: string
          nullable: true
          example: Card, Cash
        created_at:
          description: The date and time this item was created.
          type: string
          format: date-time
      required:
        - id
        - basket_id
        - order_ref
        - order_status
        - revenue_date
        - item_date
        - quantity
        - offering_id
        - offering_type
        - offering_name
        - created_at
    ServiceChargeItemTotals:
      type: object
      title: ServiceChargeItemTotals
      additionalProperties: false
      properties:
        service_charge_total:
          description: The total of all service charge amounts for the matching items.
          type: integer
          example: 760
        total_unique_orders:
          description: The number of orders matching the given filters.
          type: integer
          example: 2
        total_items:
          description: The total number of basket items matching the given filters.
          type: integer
          example: 5
    ListServiceChargeItemsResponse:
      title: ListServiceChargeItemsResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ServiceChargeItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/ServiceChargeItemTotals'
      required:
        - data
        - meta
        - links
        - totals
    TipBreakdownItem:
      type: object
      title: TipBreakdownItem
      additionalProperties: false
      properties:
        tip_item_id:
          type: string
          format: uuid
          description: The unique identifier for the tip item.
          example: a0f41964-78e1-474c-9fff-44ebaad9a6d1
        basket_item_id:
          type: string
          format: object-id
          description: The basket item ID to which the tip is applied.
          example: 697b8493694753489003695e
        amount:
          type: integer
          description: The amount of tip, in minor units.
          example: 1389
        gross_amount:
          type: integer
          description: The gross tip amount, in minor units, before any deductions.
          example: 1667
        allocation_method:
          type: string
          description: The method used to allocate the tip (e.g., direct allocation, package ratio).
          example: direct allocation (package ratio 16.67%)
        offering_name:
          type: string
          description: The name of the offering associated with the basket item.
          example: Consultation with Dr. Smith
      required:
        - tip_item_id
        - basket_item_id
        - amount
        - gross_amount
        - allocation_method
        - offering_name
    schemas_PractitionerSummary:
      type: object
      title: PractitionerSummary
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the practitioner.
        name:
          type: string
          description: The name of the practitioner.
          example: Jasmine
      required:
        - id
        - name
    TipItem:
      type: object
      title: TipItem
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the item.
        basket_id:
          type: string
          format: object-id
          description: The ID of the basket this item belongs to.
        order_ref:
          type: string
          description: The order ref of the basket this item belongs to.
          example: TRY03
        order_status:
          type: string
          description: The status of the basket this item belongs to.
          example: settled
        order_date:
          type: string
          format: date-time
          nullable: true
          description: The date and time the order was submitted.
        revenue_date:
          type: string
          format: date
          nullable: true
          description: The revenue date of the basket this item belongs to.
        total_cost:
          type: integer
          nullable: true
          description: The total cost of the item, in minor units. Null for package items.
          example: 15000
        net_total:
          type: integer
          nullable: true
          description: The net total of the item, in minor units. Null for package items.
          example: 12000
        tip_amount:
          type: integer
          nullable: true
          description: The tip amount for this item, in minor units. Null for package items.
          example: 2500
        gross_tip_amount:
          type: integer
          nullable: true
          description: The gross tip amount for this item, in minor units, before any deductions. Null for package items.
          example: 3000
        tip_breakdown:
          type: array
          description: Detailed breakdown of the tip allocation.
          items:
            $ref: '#/components/schemas/TipBreakdownItem'
        practitioners:
          type: array
          items:
            $ref: '#/components/schemas/schemas_PractitionerSummary'
        payment_methods:
          type: string
          example: Manual (Cash)
      required:
        - id
        - basket_id
        - order_ref
        - order_status
    TipItemTotals:
      type: object
      title: TipItemTotals
      additionalProperties: false
      properties:
        total_tip_items:
          type: integer
          description: The total number of orders with tips.
          example: 2500
        total_unique_orders:
          type: integer
          description: The total count of orders for the given filters.
          example: 10
        tip_total:
          type: integer
          description: The total of all tip amounts for the matching items.
          example: 5
        gross_tip_amount:
          type: integer
          description: The total of all gross tip amounts for the matching items, before any deductions.
          example: 6000
    ListTipItemsResponse:
      title: ListTipItemsResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/TipItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/TipItemTotals'
      required:
        - data
        - meta
        - links
        - totals
    schemas_Session-2:
      type: object
      title: Session
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the session.
        session_type_id:
          type: string
          format: mongo-id
          description: The ID of the session type.
        session_type_name:
          type: string
          description: The name of the session type.
        practitioner_id:
          type: string
          format: mongo-id
          description: The ID of the practitioner assigned to this session.
        practitioner:
          $ref: '#/components/schemas/PractitionerSummary'
        room_id:
          type: string
          format: mongo-id
          description: The ID of the room where the session is taking place.
        room:
          $ref: '#/components/schemas/RoomSummary'
        start_time:
          type: string
          format: date-time
          description: The date and time that the session starts.
        end_time:
          type: string
          format: date-time
          description: The date and time that the session ends.
        duration:
          type: integer
          description: The duration of the session in minutes.
        capacity:
          type: integer
          description: The total allowed capacity of the session.
        num_booked:
          type: integer
          description: The total number of guests that have booked this session.
        remaining_capacity:
          type: integer
          description: The remaining capacity of the session.
        max_baskets:
          type: integer
          description: The maximum number of orders that will be allowed to have bookings for this session.
        waitlist_enabled:
          type: boolean
          description: Whether the waitlist is enabled for this session.
        num_waitlisted:
          type: integer
          description: The total number of guests on the waitlist for this session.
        price:
          type: integer
          description: The price of this session.
        currency:
          type: string
          format: The currency used for this session.
          example: GBP
        created_at:
          type: string
          format: date-time
          description: The date and time this session was created.
        updated_at:
          type: string
          format: date-time
          description: The date and time this session was updated.
        deleted_at:
          type: string
          format: date-time
          description: The date and time this session was cancelled.
        site_id:
          type: string
          format: uuid
          description: The ID of the site where this session is taking place.
      required:
        - id
        - session_type_id
        - session_type_name
        - practitioner_id
        - practitioner
        - room_id
        - room
        - start_time
        - end_time
        - duration
        - capacity
        - num_booked
        - remaining_capacity
        - max_baskets
        - waitlist_enabled
        - num_waitlisted
        - price
        - currency
        - created_at
        - updated_at
        - site_id
    SessionListTotals:
      type: object
      title: SessionListTotals
      additionalProperties: false
      properties:
        capacity:
          type: integer
          description: The total allowed capacity of all sessions.
        num_booked:
          type: integer
          description: The total number of guests that have booked across all sessions.
        remaining_capacity:
          type: integer
          description: The total remaining capacity of all sessions.
      required:
        - capacity
        - num_booked
        - remaining_capacity
    ListSessionsResponse:
      title: ListSessionsResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/schemas_Session-2'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/SessionListTotals'
      required:
        - data
        - meta
        - links
        - totals
    schemas_RevenueCentre:
      type: object
      title: RevenueCentre
      additionalProperties: false
      properties:
        revenue_centre_id:
          type: string
          description: The ID of the revenue centre.
          example: fb
        revenue_centre_label:
          type: string
          description: The name of the revenue centre.
          example: Food & Beverage
        gross_revenue:
          type: integer
          description: The gross revenue allocated to an individual revenue centre.
          example: 10000
        net_revenue:
          type: integer
          description: The net revenue allocated to an individual revenue centre.
          example: 8000
        num_items:
          type: integer
          description: The number of items.
          example: 5
      required:
        - revenue_centre_id
        - revenue_centre_label
        - gross_revenue
        - net_revenue
        - num_items
    RevenueByCentreStats:
      type: object
      title: RevenueByCentreStats
      additionalProperties: false
      properties:
        by_revenue_centre:
          type: array
          items:
            $ref: '#/components/schemas/schemas_RevenueCentre'
        num_items:
          type: integer
          description: The number of items.
          example: 35
        total_gross:
          type: integer
          description: The gross revenue across all submitted orders.
          example: 8000
        total_net:
          type: integer
          description: The net revenue across all submitted orders.
          example: 6000
        item_average_gross:
          type: integer
          description: The average gross revenue per item.
          example: 5000
        item_average_net:
          type: integer
          description: The average net revenue per item.
          example: 3000
      required:
        - by_revenue_centre
        - num_items
        - total_gross
        - total_net
        - item_average_gross
        - item_average_net
    RevenueByCentreByDateStats:
      type: object
      title: RevenueByCentreByDateStats
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: The revenue date of the item.
        items_paid:
          $ref: '#/components/schemas/RevenueByCentreStats'
        items_unpaid:
          $ref: '#/components/schemas/RevenueByCentreStats'
        totals:
          $ref: '#/components/schemas/RevenueByCentreStats'
      required:
        - date
        - items_paid
        - items_unpaid
        - totals
    RevenueByCentreTotalsStats:
      type: object
      title: RevenueByCentreTotalsStats
      additionalProperties: false
      properties:
        items_paid:
          $ref: '#/components/schemas/RevenueByCentreStats'
        items_unpaid:
          $ref: '#/components/schemas/RevenueByCentreStats'
        totals:
          $ref: '#/components/schemas/RevenueByCentreStats'
      required:
        - items_paid
        - items_unpaid
        - totals
    RevenueByCentreSummary:
      type: object
      title: RevenueByCentreSummary
      additionalProperties: false
      properties:
        by_day:
          type: array
          items:
            $ref: '#/components/schemas/RevenueByCentreByDateStats'
        totals:
          $ref: '#/components/schemas/RevenueByCentreTotalsStats'
      required:
        - by_day
        - totals
    RevenueByCentreMeta:
      type: object
      title: RevenueByCentreMeta
      additionalProperties: false
      properties:
        revenue_centres:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreSummary'
      required:
        - revenue_centres
    RevenueCentreTotals:
      type: object
      title: RevenueCentreTotals
      additionalProperties: false
      properties:
        revenue_centre_key:
          type: string
          description: The key of the revenue centre.
          example: spa
        revenue_centre_name:
          type: string
          description: The name of the revenue centre.
          example: Spa treatments
        gross_revenue:
          type: integer
          description: The gross revenue for this revenue centre.
          example: 120000
        net_revenue:
          type: integer
          description: The net revenue for this revenue centre.
          example: 95000
        num_items:
          type: integer
          description: The number of items for this revenue centre.
          example: 3
      required:
        - revenue_centre_key
        - revenue_centre_name
        - gross_revenue
        - net_revenue
        - num_items
    OrganisationRevenueByCentreDateStats:
      type: object
      title: OrganisationRevenueByCentreDateStats
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: The date the stats in this object relate to.
        gross_revenue:
          type: integer
          description: The total gross revenue.
          example: 95000
        net_revenue:
          type: integer
          description: The total gross revenue.
          example: 78400
        item_average_gross:
          type: integer
          description: The gross average item revenue.
          example: 14500
        item_average_net:
          type: integer
          description: The net average item revenue.
          example: 11500
        by_revenue_centre:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreTotals'
      required:
        - date
        - gross_revenue
        - net_revenue
        - item_average_gross
        - item_average_net
        - by_revenue_centre
    OrganisationRevenueByCentreItemTotals:
      type: object
      title: OrganisationRevenueByCentreItemTotals
      additionalProperties: false
      properties:
        gross_revenue:
          type: integer
          description: The total gross revenue.
          example: 95000
        net_revenue:
          type: integer
          description: The total gross revenue.
          example: 78400
        item_average_gross:
          type: integer
          description: The gross average item revenue.
          example: 14500
        item_average_net:
          type: integer
          description: The net average item revenue.
          example: 11500
        by_revenue_centre:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreTotals'
      required:
        - gross_revenue
        - net_revenue
        - item_average_gross
        - item_average_net
        - by_revenue_centre
    OrganisationRevenueByCentreSiteStats:
      type: object
      title: OrganisationRevenueByCentreSiteStats
      additionalProperties: false
      properties:
        site_id:
          type: string
          format: uuid
          description: The ID of the site the stats in this object relate to.
        site_name:
          type: string
          description: The name of the site the stats in this object relate to.
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/OrganisationRevenueByCentreDateStats'
        totals:
          $ref: '#/components/schemas/OrganisationRevenueByCentreItemTotals'
      required:
        - site_id
        - site_name
        - by_date
        - totals
    OrganisationRevenueByCentreTotals:
      type: object
      title: OrganisationRevenueByCentreTotals
      additionalProperties: false
      properties:
        gross_revenue:
          type: integer
          description: The total gross revenue.
          example: 95000
        net_revenue:
          type: integer
          description: The total net revenue.
          example: 78400
        item_average_gross:
          type: integer
          description: The gross average item revenue.
          example: 14500
        item_average_net:
          type: integer
          description: The net average item revenue.
          example: 11500
        by_revenue_centre:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreTotals'
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/OrganisationRevenueByCentreDateStats'
      required:
        - gross_revenue
        - net_revenue
        - item_average_gross
        - item_average_net
        - by_revenue_centre
    OrganisationRevenueByCentreMeta:
      type: object
      title: OrganisationRevenueByCentreMeta
      additionalProperties: false
      properties:
        currency:
          type: string
          description: The curreny for all monetary values in the report.
          example: gbp
        revenue_centres:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreSummary'
      required:
        - currency
        - revenue_centres
    AuthenticationLog:
      type: object
      title: OrganisationRevenueByCentreDateStats
      additionalProperties: false
      properties:
        ip_address:
          type: string
          description: The IP address of the user.
          example: 127.0.0.1
        user_id:
          type: string
          format: uuid
          description: The ID of the user.
        user:
          type: string
          description: The name of the user.
          example: John Doe
        login_successful:
          type: boolean
          description: The status of the login.
          example: true
        login_at:
          type: string
          format: date
          description: The date the stats in this object relate to.
      required:
        - ip_address
        - user_id
        - user
        - login_successful
        - login_at
    OrganisationRevenueBySalesChannelRevenueCentre:
      type: object
      title: OrganisationRevenueBySalesChannelRevenueCentre
      additionalProperties: false
      properties:
        revenue_centre:
          type: string
          description: The key of the revenue centre
          example: spa
        gross_revenue:
          type: integer
          description: The gross revenue for this revenue centre.
          example: 120000
        net_revenue:
          type: integer
          description: The net revenue for this revenue centre.
          example: 95000
      required:
        - revenue_centre
        - gross_revenue
        - net_revenue
    OrganisationRevenueBySalesChannelItem:
      type: object
      title: OrganisationRevenueBySalesChannelItem
      additionalProperties: false
      properties:
        sales_channel_id:
          type: string
          format: object-id
          description: The ID of the sales channel.
        sales_channel_name:
          type: string
          description: The name of the sales channel.
          example: Website
        num_baskets:
          type: integer
          description: The number of baskets from this sales channel.
          example: 9
        gross_revenue:
          type: integer
          description: The gross revenue for baskets from this sales channel.
          example: 120000
        net_revenue:
          type: integer
          description: The net revenue for baskets from this sales channel.
          example: 95000
        revenue_centres:
          type: array
          description: Revenues for this sales channel broken down by revenue centre.
          items:
            $ref: '#/components/schemas/OrganisationRevenueBySalesChannelRevenueCentre'
      required:
        - sales_channel_id
        - sales_channel_name
        - num_baskets
        - gross_revenue
        - net_revenue
        - revenue_centres
    OrganisationRevenueBySalesChannelSite:
      type: object
      title: OrganisationRevenueBySalesChannelSite
      additionalProperties: false
      properties:
        site_id:
          type: string
          format: uuid
          description: The ID of the site these stats relate to
        site_name:
          type: string
          description: The name of the site these stats relate to
          example: Palm Tree Spa
        by_sales_channel:
          type: array
          items:
            $ref: '#/components/schemas/OrganisationRevenueBySalesChannelItem'
      required:
        - site_id
        - site_name
        - by_sales_channel
    OrganisationRevenueBySalesChannelTotals:
      type: object
      title: OrganisationRevenueBySalesChannelTotals
      additionalProperties: false
      properties:
        by_sales_channel:
          type: array
          items:
            $ref: '#/components/schemas/OrganisationRevenueBySalesChannelItem'
      required:
        - by_sales_channel
    OrganisationRevenueBySalesChannelStats:
      type: object
      title: OrganisationRevenueBySalesChannelStats
      additionalProperties: false
      properties:
        by_site:
          type: array
          items:
            $ref: '#/components/schemas/OrganisationRevenueBySalesChannelSite'
        totals:
          $ref: '#/components/schemas/OrganisationRevenueBySalesChannelTotals'
      required:
        - by_site
        - totals
    SalesChannelSummary:
      type: object
      title: SalesChannelSummary
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the sales channel.
        name:
          type: string
          description: The name of the sales channel.
          example: Website
      required:
        - id
        - name
    OrganisationRevenueBySalesChannelMeta:
      type: object
      title: OrganisationRevenueBySalesChannelMeta
      additionalProperties: false
      properties:
        sales_channels:
          type: array
          items:
            $ref: '#/components/schemas/SalesChannelSummary'
        revenue_centres:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreSummary'
        currency:
          type: string
          description: The curreny for all monetary values in the report.
          example: gbp
      required:
        - sales_channels
        - revenue_centres
        - currency
    OrganisationTopOfferingsOffering:
      type: object
      title: OrganisationTopOfferingsOffering
      additionalProperties: false
      properties:
        offering_id:
          type: string
          format: object-id
          description: The ID of the offering.
        offering_type:
          type: string
          description: The type of the offering.
          example: appointment
        offering_name:
          type: string
          description: The name of the offering.
          example: 60 minute massage
        site_id:
          type: string
          format: uuid
          description: The ID of the site this offering belongs to.
        site_name:
          type: string
          description: The name of the site this offering belongs to.
          example: Palm Tree Spa
        num_standalone_items:
          type: integer
          description: The number of this offering that were sold as standalone items.
          example: 12
        num_package_items:
          type: integer
          description: The number of this offering that were sold as part of a package.
          example: 4
        gross_revenue:
          type: integer
          description: The gross revenue for this offering.
          example: 95000
        net_revenue:
          type: integer
          description: The net revenue for this offering.
          example: 78400
      required:
        - offering_id
        - offering_type
        - offering_name
        - site_id
        - site_name
        - num_standalone_items
        - num_package_items
        - gross_revenue
        - net_revenue
    OfferingTypeTotals:
      type: object
      title: OfferingTypeTotals
      additionalProperties: false
      properties:
        offering_type:
          type: string
          description: The type of the offering.
          example: appointment
        num_standalone_items:
          type: integer
          description: The number of items of this type that were sold as standalone items.
          example: 12
        num_package_items:
          type: integer
          description: The number of items of this type that were sold as part of a package.
          example: 4
        gross_revenue:
          type: integer
          description: The gross revenue for this offering type.
          example: 95000
        net_revenue:
          type: integer
          description: The net revenue for this offering type.
          example: 78400
      required:
        - offering_type
        - num_standalone_items
        - num_package_items
        - gross_revenue
        - net_revenue
    OrganisationTopOfferingsTotals:
      type: object
      title: OrganisationTopOfferingsTotals
      additionalProperties: false
      properties:
        by_offering_type:
          type: array
          items:
            $ref: '#/components/schemas/OfferingTypeTotals'
      required:
        - by_offering_type
    OrganisationTopOfferingsMeta:
      type: object
      title: OrganisationTopOfferingsMeta
      additionalProperties: false
      properties:
        currency:
          type: string
          description: The curreny for all monetary values in the report.
          example: gbp
      required:
        - currency
    schemas_CustomerLabel-3:
      type: object
      title: CustomerLabel
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the label
        value:
          type: string
          description: The name of the label
          example: VIP
        colour:
          type: string
          description: A hex colour code excluding the preceding \# which this label will be rendered as.
          example: ff6634
      required:
        - id
        - value
        - colour
    LeadMemberSummary:
      title: LeadMemberSummary
      type: object
      additionalProperties: false
      description: The lead member of a membership
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the lead member.
        full_name:
          type: string
          description: The full name of the lead member.
        email:
          type: string
          description: The email address of the lead member.
        phone:
          type: string
          description: The phone number of the lead member.
        labels:
          type: array
          items:
            $ref: '#/components/schemas/schemas_CustomerLabel-3'
      required:
        - id
        - full_name
        - email
        - phone
        - labels
    MembershipTypeSummary:
      type: object
      title: MembershipTypeSummary
      additionalProperties: false
      description: A summary of a membership type.
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the membership type.
        name:
          type: string
          description: The name of the membership type.
      required:
        - id
        - name
    MembershipRateSummary:
      type: object
      title: MembershipRateSummary
      additionalProperties: false
      description: A summary of a membership rate.
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the membership rate.
        name:
          type: string
          description: The name of the membership rate.
      required:
        - id
        - name
    ProjectedMembershipRevenues:
      type: object
      title: ProjectedMembershipRevenues
      additionalProperties: false
      description: A membership summary with projected revenue information.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the membership.
        membership_number:
          type: string
          description: The membership number of the membership.
          example: '00000014'
        lead_member:
          $ref: '#/components/schemas/LeadMemberSummary'
        start_date:
          type: string
          format: datetime
          description: The start date of the membership.
        end_date:
          type: string
          format: datetime
          description: The end date of the membership.
        membership_type:
          $ref: '#/components/schemas/MembershipTypeSummary'
        membership_rate:
          $ref: '#/components/schemas/MembershipRateSummary'
        status:
          type: string
          description: The status of the membership
          enum:
            - active
            - needs_dd_mandate
            - needs_attention
            - reserved
            - inactive
            - expired
            - upcoming
        gross_amount:
          type: integer
          description: The gross amount of the membership.
        net_amount:
          type: integer
          description: The net amount of the membership.
        duration_days:
          type: integer
          description: The duration of the membership in days.
        elapsed_days:
          type: integer
          description: The number of days elapsed since the membership started.
        remaining_days:
          type: integer
          description: The number of days remaining until the membership ends.
        gross_remaining_balance:
          type: integer
          description: The gross remaining balance of the membership.
        net_remaining_balance:
          type: integer
          description: The net remaining balance of the membership.
      required:
        - id
        - membership_number
        - lead_member
        - start_date
        - end_date
        - membership_type
        - membership_rate
        - status
        - gross_amount
        - net_amount
        - duration_days
        - elapsed_days
        - remaining_days
        - gross_remaining_balance
        - net_remaining_balance
    ListProjectedMembershipRevenueResponse:
      title: ListProjectedMembershipRevenueResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProjectedMembershipRevenues'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    MonthlyRevenue:
      type: object
      title: MonthlyRevenue
      additionalProperties: false
      properties:
        month:
          type: string
          format: date
          description: The month of the projected revenue in YYYY-MM format.
        gross_amount:
          type: integer
          description: The gross amount of the projected revenue for this month.
        net_amount:
          type: integer
          description: The net amount of the projected revenue for this month.
        days:
          type: integer
          description: The number of days in the month there is revenue for.
      required:
        - month
        - gross_amount
        - net_amount
        - days
    ProjectedMembershipRevenuesByMonth:
      type: object
      title: ProjectedMembershipRevenuesByMonth
      additionalProperties: false
      description: A membership summary with projected revenue information.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the membership.
        membership_number:
          type: string
          description: The membership number of the membership.
          example: '00000014'
        lead_member:
          $ref: '#/components/schemas/LeadMemberSummary'
        membership_type:
          $ref: '#/components/schemas/MembershipTypeSummary'
        membership_rate:
          $ref: '#/components/schemas/MembershipRateSummary'
        status:
          type: string
          description: The status of the membership
          enum:
            - active
            - needs_dd_mandate
            - needs_attention
            - reserved
            - inactive
            - expired
            - upcoming
        remaining_days:
          type: integer
          description: The number of days remaining until the membership ends.
        gross_remaining_balance:
          type: integer
          description: The gross remaining balance of the membership.
        net_remaining_balance:
          type: integer
          description: The net remaining balance of the membership.
        monthly_revenues:
          type: array
          items:
            $ref: '#/components/schemas/MonthlyRevenue'
      required:
        - id
        - membership_number
        - lead_member
        - membership_type
        - membership_rate
        - status
        - remaining_days
        - gross_remaining_balance
        - net_remaining_balance
        - monthly_revenues
    ListProjectedMembershipRevenueByMonthResponse:
      title: ListProjectedMembershipRevenueByMonthResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ProjectedMembershipRevenuesByMonth'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
      required:
        - data
        - meta
        - links
    MembershipCreditItem:
      type: object
      title: MembershipCreditItem
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the item.
        membership_number:
          type: string
          description: The membership number associated with the membership credit.
          example: '000047569'
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer associated with the membership credit.
        first_name:
          type: string
          description: The first name of the customer associated with the membership credit.
          example: John
        last_name:
          type: string
          description: The last name of the customer associated with the membership credit.
          example: Doe
        email:
          type: string
          format: email
          description: The email of the customer associated with the membership credit.
        total_credits:
          type: integer
          description: The total number of credits available on this membership.
          example: 15
        multi_use_credits:
          type: integer
          description: The number of multi-use credits available on this membership.
          example: 12
      required:
        - id
        - first_name
        - last_name
        - email
        - total_credits
        - multi_use_credits
    MembershipCreditItemTotals:
      type: object
      title: MembershipCreditItemTotals
      additionalProperties: false
      properties:
        total_memberships:
          type: integer
          description: The total number of memberships.
          example: 2500
        total_credits:
          type: integer
          description: The total number of credits across all memberships.
          example: 10
        total_multi_use_credits:
          type: integer
          description: The total number of multi-use credits across all memberships.
          example: 5
    ListMembershipCreditsResponse:
      title: ListMembershipCreditsResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/MembershipCreditItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/MembershipCreditItemTotals'
      required:
        - data
        - meta
        - links
        - totals
    MembershipCreditUsageItem:
      type: object
      title: MembershipCreditUsageItem
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the credit.
        coupon:
          type: object
          title: MembershipCreditUsageItemCoupon
          additionalProperties: false
          description: The coupon associated with this credit.
          properties:
            name:
              type: string
              nullable: true
              description: The name of the coupon.
              example: Spa Day Pass
            description:
              type: string
              nullable: true
              description: The description of the coupon.
            code:
              type: string
              description: The coupon code.
          required:
            - name
            - description
            - code
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer who owns this credit.
        first_name:
          type: string
          nullable: true
          description: The first name of the customer.
          example: John
        last_name:
          type: string
          nullable: true
          description: The last name of the customer.
          example: Doe
        email:
          type: string
          format: email
          nullable: true
          description: The email address of the customer.
        membership:
          type: object
          title: MembershipCreditUsageItemMembership
          additionalProperties: false
          description: The membership associated with this credit.
          properties:
            id:
              type: string
              format: uuid
              nullable: true
              description: The ID of the membership.
            number:
              type: string
              nullable: true
              description: The membership number of the customer within the membership.
              example: '47569'
            type_name:
              type: string
              nullable: true
              description: The name of the membership type.
              example: Gold Membership
            status:
              type: string
              nullable: true
              description: The current status of the membership.
              enum:
                - active
                - inactive
                - expired
                - upcoming
                - needs_attention
                - reserved
          required:
            - id
            - number
            - type_name
            - status
        multi_use:
          type: boolean
          description: Whether this credit can be redeemed multiple times.
        status:
          type: string
          description: The computed status of this credit.
          enum:
            - redeemable
            - redeemed
            - revoked
            - expired
        issued_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit was issued.
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit expires.
        redeemed_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit was redeemed.
        revoked_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit was revoked.
      required:
        - id
        - customer_id
        - multi_use
        - status
    MembershipCreditUsageTotals:
      type: object
      title: MembershipCreditUsageTotals
      additionalProperties: false
      properties:
        total_credits:
          type: integer
          description: The total number of credits matching the current filters.
          example: 150
        total_redeemed:
          type: integer
          description: The number of credits that have been redeemed.
          example: 45
        total_revoked:
          type: integer
          description: The number of credits that have been revoked.
          example: 10
        total_expired:
          type: integer
          description: The number of credits that have expired without being redeemed.
          example: 20
        total_redeemable:
          type: integer
          description: The number of credits that are currently redeemable.
          example: 75
        total_multi_use:
          type: integer
          description: The number of multi-use credits.
          example: 30
      required:
        - total_credits
        - total_redeemed
        - total_revoked
        - total_expired
        - total_redeemable
        - total_multi_use
    ListMembershipCreditUsageResponse:
      title: ListMembershipCreditUsageResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/MembershipCreditUsageItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/MembershipCreditUsageTotals'
      required:
        - data
        - meta
        - links
        - totals
    CourseCreditItem:
      type: object
      title: CourseCreditItem
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the credit.
        coupon:
          type: object
          title: CourseCreditItemCoupon
          additionalProperties: false
          description: The coupon associated with this credit.
          properties:
            name:
              type: string
              nullable: true
              description: The name of the coupon.
              example: 10 Session PT Package
            description:
              type: string
              nullable: true
              description: The description of the coupon.
            code:
              type: string
              nullable: true
              description: The coupon code.
          required:
            - name
            - description
            - code
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer who owns this credit.
        first_name:
          type: string
          nullable: true
          description: The first name of the customer.
          example: John
        last_name:
          type: string
          nullable: true
          description: The last name of the customer.
          example: Doe
        email:
          type: string
          format: email
          nullable: true
          description: The email address of the customer.
        course:
          type: object
          title: CourseCreditItemCourse
          additionalProperties: false
          description: The course type this credit was issued from.
          properties:
            id:
              type: string
              format: object-id
              nullable: true
              description: The ID of the course type.
            name:
              type: string
              nullable: true
              description: The name of the course type.
              example: Personal Training Package
          required:
            - id
            - name
        status:
          type: string
          description: The computed status of this credit.
          enum:
            - redeemable
            - redeemed
            - revoked
            - expired
        value:
          type: integer
          description: The monetary value of the credit, in minor units (e.g. pence).
          example: 5000
        issued_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit was issued.
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit expires.
        redeemed_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit was redeemed.
        revoked_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time the credit was revoked.
      required:
        - id
        - customer_id
        - status
        - value
    CourseCreditTotals:
      type: object
      title: CourseCreditTotals
      additionalProperties: false
      properties:
        total_credits:
          type: integer
          description: The total number of credits matching the current filters.
          example: 150
        total_redeemed:
          type: integer
          description: The number of credits that have been redeemed.
          example: 45
        total_revoked:
          type: integer
          description: The number of credits that have been revoked.
          example: 10
        total_expired:
          type: integer
          description: The number of credits that have expired without being redeemed.
          example: 20
        total_redeemable:
          type: integer
          description: The number of credits that are currently redeemable.
          example: 75
        outstanding_value:
          type: integer
          description: The total value of redeemable credits, in minor units. This is the outstanding course-credit liability.
          example: 375000
        redeemed_value:
          type: integer
          description: The total value of redeemed credits, in minor units.
          example: 225000
        currency:
          type: string
          description: The ISO 4217 currency code the values are expressed in.
          example: GBP
      required:
        - total_credits
        - total_redeemed
        - total_revoked
        - total_expired
        - total_redeemable
        - outstanding_value
        - redeemed_value
        - currency
    ListCourseCreditResponse:
      title: ListCourseCreditResponse
      additionalProperties: false
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CourseCreditItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/CourseCreditTotals'
      required:
        - data
        - meta
        - links
        - totals
    KpiStatsItem:
      title: KpiStatsItem
      additionalProperties: false
      type: object
      required:
        - date
        - all_baskets_count
        - all_baskets_average_value
        - website_baskets_count
        - website_baskets_average_value
      properties:
        date:
          type: string
          format: date
          description: The date for this bucket in `yyyy-MM-dd` format.
          example: '2024-01-15'
        all_baskets_count:
          type: integer
          description: Total number of submitted baskets on this date (all sources).
          example: 42
        all_baskets_average_value:
          type: integer
          description: Average `total_cost` in minor currency units across all baskets on this date.
          example: 7500
        website_baskets_count:
          type: integer
          description: Number of submitted baskets with `source=shop_v2` on this date.
          example: 28
        website_baskets_average_value:
          type: integer
          description: Average `total_cost` in minor currency units for website baskets on this date.
          example: 6800
    KpiStatsSummary:
      title: KpiStatsSummary
      additionalProperties: false
      type: object
      description: Aggregated totals across the entire date range.
      required:
        - all_baskets_count
        - all_baskets_average_value
        - website_baskets_count
        - website_baskets_average_value
      properties:
        all_baskets_count:
          type: integer
          description: Total number of submitted baskets across the entire date range (all sources).
          example: 420
        all_baskets_average_value:
          type: integer
          description: Average `total_cost` in minor currency units across all baskets in the range.
          example: 7200
        website_baskets_count:
          type: integer
          description: Total number of submitted baskets with `source=shop_v2` across the entire date range.
          example: 280
        website_baskets_average_value:
          type: integer
          description: Average `total_cost` in minor currency units for website baskets in the range.
          example: 6500
    KpiStatsMeta:
      title: KpiStatsMeta
      additionalProperties: false
      type: object
      required:
        - currency
      properties:
        currency:
          type: string
          description: ISO 4217 currency code for the site.
          example: gbp
    KpiStatsReport:
      title: KpiStatsReport
      additionalProperties: false
      type: object
      required:
        - data
        - meta
      properties:
        data:
          title: KpiStatsData
          additionalProperties: false
          type: object
          required:
            - by_date
            - summary
          properties:
            by_date:
              type: array
              description: Per-day basket statistics. Includes an entry for every date in the requested range.
              items:
                $ref: '#/components/schemas/KpiStatsItem'
            summary:
              $ref: '#/components/schemas/KpiStatsSummary'
        meta:
          $ref: '#/components/schemas/KpiStatsMeta'
    MembershipTypeLocaleStrings:
      title: MembershipTypeLocaleStrings
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
          description: The localised name for this membership type in the given locale.
          example: Spa Membership
        description:
          type: string
          nullable: true
          description: The localised description HTML for this membership type in the given locale.
          example: <p>Enjoy exclusive access to our spa facilities.</p>
        terms:
          type: string
          nullable: true
          description: The localised terms and conditions HTML for this membership type in the given locale.
          example: <p>Membership is non-transferable and subject to our standard terms.</p>
      required:
        - name
        - description
        - terms
    schemas_MembershipTypeSummary:
      title: MembershipTypeSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the membership type this rule belongs to
        name:
          type: string
          description: The name of the membership type this rule belongs to
          example: Gold tier
      required:
        - id
        - name
    MembershipCreditRule:
      title: MembershipCreditRule
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the credit rule
        membership_type_id:
          type: string
          format: uuid
          description: The ID of the membership type this rule relates to
        membership_type:
          $ref: '#/components/schemas/schemas_MembershipTypeSummary'
        coupon_id:
          type: string
          description: The ID of the coupon which will be issued
        coupon_name:
          type: string
          description: The name of the coupon which will be issued
        coupon_description:
          type: string
          description: The description of the coupon which will be issued
        roll_over:
          type: boolean
          description: |
            If true, unused credits will roll over to the next month.
            Otherwise, any unused credits will be marked as expired on the next billing period.
        issue_on_signup:
          type: boolean
          description: |
            If true, the credit will be issued when new customers sign up for the given membership type.
            Otherwise, the credit will be issued only on the monthly billing schedule.
        multi_use:
          type: boolean
          description: |
            If true, the credit can be used an unlimited number of times until the expiry date.
        for_lead_booker_only:
          type: boolean
          description: |
            If true, the credit will only be issued for the lead booker of an order. If false, the credit will be issued for all guests on the order, including non-members.
        issuing_frequency:
          type: string
          enum:
            - billing_cycle
            - P0D
            - P1M
            - P3M
            - P6M
            - P1Y
          description: |
            The frequency that this credit is issued.
            The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1M
        created_at:
          type: string
          format: date-time
          description: The date and time which the credit rule was created
          example: '2026-01-01T00:00:00+00:00'
        updated_at:
          type: string
          format: date-time
          description: The date and time which the credit rule was last updated
          example: '2026-01-01T00:00:00+00:00'
      required:
        - id
        - membership_type_id
        - coupon_id
        - coupon_name
        - coupon_description
        - roll_over
        - issue_on_signup
        - multi_use
        - for_lead_booker_only
        - issuing_frequency
        - created_at
        - updated_at
    MembershipSummary:
      title: MembershipSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the membership
          format: uuid
        membership_number:
          type: string
          description: The membership number
          example: '00000014'
        type_name:
          type: string
          description: The name of the membership type
          example: Gold Membership
        customer_id:
          type: string
          format: uuid
          description: The ID of the lead customer
        customer_name:
          type: string
          description: The name of the lead customer
          example: Jane Jones
      required:
        - id
        - membership_number
        - type_name
        - customer_id
    PaymentProcessorData:
      title: PaymentProcessorData
      type: object
      additionalProperties: false
      properties:
        cardholder_name:
          type: string
          description: The name of the cardholder, if applicable
          example: Mrs J Jones
          nullable: true
        last_4:
          type: string
          description: The last four digits of the payment method, if applicable
          example: 4001
          nullable: true
        processor_type:
          type: string
          description: The processor's name for the type of payment used
          example: Cash
          nullable: true
        processor_type_id:
          type: string
          format: object-id
          description: The processor's ID for the type of payment used
          nullable: true
    schemas_UserSummary-2:
      title: UserSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the user
          format: uuid
        full_name:
          type: string
          description: The full name of the user
          example: Jane Jenkins
      required:
        - id
        - full_name
    RefundProcessorData:
      title: RefundProcessorData
      type: object
      additionalProperties: false
      properties:
        processor:
          type: string
          description: The name of processor used for this refund
          example: adyen
        processor_id:
          type: string
          description: The processor's ID for the refund
          example: re_64301e0b2df9d11814010ea6
          nullable: true
      required:
        - processor
        - processor_id
    MembershipChargeRefund:
      title: MembershipChargeRefund
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the membership charge refund
          format: uuid
        status:
          type: string
          description: The status of the refund
          example: succeeded
        amount:
          type: string
          description: The amount of the refund
          example: 995
        currency:
          type: string
          description: The currency of the refund
          example: gbp
        notes:
          type: string
          description: Any notes associated with the refund
          example: Gesture of good will
          nullable: true
        failure_reason:
          type: string
          description: A reason code for the failure, if applicable
          example: invalid_details
          nullable: true
        refunded_by:
          description: The user who processed this refund
          nullable: true
          $ref: '#/components/schemas/schemas_UserSummary-2'
        processor_data:
          type: object
          $ref: '#/components/schemas/RefundProcessorData'
        created_at:
          type: string
          format: date-time
          description: The datetime which the refund was created
        updated_at:
          type: string
          format: date-time
          description: The datetime which the refund was last updated
      required:
        - id
        - status
        - amount
        - currency
        - notes
        - processor_data
        - created_at
        - updated_at
    MembershipCharge:
      title: MembershipCharge
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The ID of the membership charge
          format: uuid
        membership:
          description: Summary details of the membership this charge relates to
          $ref: '#/components/schemas/MembershipSummary'
        processor:
          type: string
          description: The processor of the payment
          example: adyen
        processor_data:
          $ref: '#/components/schemas/PaymentProcessorData'
        amount:
          type: integer
          description: The amount of the charge, in the smallest units
          example: 3995
        original_amount:
          type: integer
          description: The original amount of the charge, in the smallest units
          example: 3995
        currency:
          type: string
          description: The code of the currency for the charge
          example: gbp
        tax:
          type: string
          description: The amount of tax calculated for this charge
          example: 1000
        status:
          type: string
          description: The status of the charge
          example: succeeded
        description:
          type: string
          description: A description of the charge
          nullable: true
        can_download_receipt:
          type: boolean
          description: Whether a receipt is available for this charge
        amount_refunded:
          type: integer
          description: The total amount refunded for this charge
        refunded:
          type: boolean
          description: Whether this charge has been fully refunded
        refunds:
          type: array
          description: An array of refunds against this charge
          items:
            $ref: '#/components/schemas/MembershipChargeRefund'
        site_id:
          type: string
          description: The ID of the site this charge belongs to
          format: uuid
        billing_period_from:
          type: string
          format: date
          description: The first date of the billing period
        billing_period_to:
          type: string
          format: date
          description: The last date of the billing period
        processing_at:
          type: string
          format: date-time
          description: The datetime when the charge started processing
        created_at:
          type: string
          format: date-time
          description: The datetime when the charge was created
        updated_at:
          type: string
          format: date-time
          description: The datetime when the charge was last updateed
      required:
        - id
        - membership
        - processor
        - processor_data
        - amount
        - currency
        - tax
        - status
        - description
        - can_download_receipt
        - amount_refunded
        - refunded
        - refunds
        - site_id
        - billing_period_from
        - billing_period_to
        - created_at
        - updated_at
    MembershipSmsMessageSummary:
      title: MembershipSmsMessageSummary
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the SMS message.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the SMS message is associated with.
        site_id:
          type: string
          format: uuid
          description: The ID of the site the SMS message is associated with.
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer the SMS message was sent to.
        membership_id:
          type: string
          format: uuid
          description: The ID of the membership the SMS message is associated with.
        from:
          type: string
          description: The sender of the SMS message.
          example: Trybe
        to:
          type: string
          description: The recipient of the SMS message. This is a valid mobile number.
          example: '+447123456789'
        message:
          type: string
          description: |
            The contents of the SMS message.
        message_type:
          type: string
          description: The type of message the SMS message is.
          enum:
            - billing_details_request
        message_delivered:
          type: boolean
          description: Whether the SMS message was successfully delivered.
          example: true
        created_at:
          type: string
          format: date-time
          description: The date and time the SMS message was created.
          example: '2024-02-02T12:00:00Z'
        sent_at:
          type: string
          format: date-time
          description: The date and time the SMS message was sent.
          example: '2024-02-02T12:00:00Z'
      required:
        - id
        - organisation_id
        - site_id
        - customer_id
        - from
        - to
        - message
        - message_type
        - message_delivered
        - created_at
    MembershipSmsMessagePreview:
      title: MembershipSmsMessagePreview
      type: object
      additionalProperties: false
      properties:
        message:
          type: string
          description: The contents of the SMS message.
          example: |
            Your Premium Membership membership is almost ready! Please provide payment details for your membership payments. Set up here: https://example.com/confirm
        site_id:
          type: string
          format: uuid
          description: The ID of the site the SMS message is associated with.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation the SMS message is associated with.
      required:
        - message
        - site_id
        - organisation_id
    User:
      title: User
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: |
            Stable unique identifier for the user. Treat as opaque even
            though the underlying format is a UUID — never parse or
            construct it client-side.
          format: uuid
          example: 5e1e3f6c-2a44-4f6e-8c61-9c1f7d2e1c11
        name:
          type: string
          description: |
            The user's display name, typically `given_name family_name`
            but may diverge for users who supplied an alternative.
          example: John Smith
        given_name:
          type: string
          description: |
            The user's first / given name, as supplied at registration or
            sync from the identity provider.
          example: John
        family_name:
          type: string
          description: |
            The user's surname / family name, as supplied at registration
            or sync from the identity provider.
          example: Smith
        email:
          type: string
          description: |
            The user's primary email address. Used for sign-in,
            notification delivery, and forms-of-identity verification.
          format: email
          example: john.smith@example.com
        email_verified:
          type: boolean
          description: Whether the user has verified their email address
          example: true
        organisation_id:
          type: string
          description: |
            ID of the organisation this user is scoped to. Every user
            belongs to exactly one organisation; cross-org access is
            modelled via separate user accounts.
          format: uuid
          example: 9c3ad1e2-2d1b-4f4f-9e07-6d6c4f3a2b1a
        organisation_name:
          type: string
          nullable: true
          description: |
            Human-readable name of the user's organisation, denormalised
            onto the User payload so callers don't need to make a second
            fetch. `null` when the organisation has been archived.
          example: Trybe Spa Group
        site_ids:
          type: array
          description: The IDs of the sites that this user belongs to
          items:
            type: string
            format: uuid
        avatar_id:
          type: string
          description: |
            ID of the `Media` record holding the user's avatar image. Use
            `avatar.urls` on this same payload to render directly without
            a separate Media fetch. `null` when the user hasn't uploaded
            one.
          format: uuid
          nullable: true
          example: 7d2a1f9c-5b3e-4d8c-9f0a-2c4e6f8b1d3a
        avatar:
          $ref: '#/components/schemas/Media'
        cashier_id:
          type: string
          nullable: true
          description: |
            Optional cashier identifier linking this user to a Point of
            Sale cashier profile. `null` when the user isn't a POS
            operator.
          example: cashier-042
        status:
          type: string
          description: |
            Lifecycle status of the user account. `active` for normal
            sign-in, `disabled` for accounts locked by an admin.
          example: active
        2fa_enabled:
          type: boolean
          description: Whether 2FA is enabled for the user
          example: true
        twofa_enabled:
          type: boolean
          description: Whether 2FA is enabled for the user
          example: true
        created_at:
          type: string
          format: date-time
          description: The date and time the user was created
          example: '2020-01-01T00:00:00.000Z'
        updated_at:
          type: string
          format: date-time
          description: The date and time the user was last updated
          example: '2020-01-01T00:00:00.000Z'
        managed_by_sso:
          type: boolean
          description: Whether the user is managed by SSO
          example: true
        whitelisted_internal_user:
          type: boolean
          description: Whether the user is a whitelisted internal user
          example: false
      required:
        - id
        - name
        - given_name
        - family_name
        - email
        - email_verified
        - organisation_id
        - organisation_name
        - site_ids
        - avatar_id
        - status
        - twofa_enabled
        - created_at
        - updated_at
        - managed_by_sso
    Role:
      title: UserSiteRoleRole
      type: object
      additionalProperties: false
      required:
        - description
        - id
        - name
        - organisation_id
      properties:
        id:
          type: string
          description: The id of the role.
          example: beddda88-947d-4bd8-8f0c-828b187f93b2
        name:
          type: string
          description: The full name of the role.
          example: Therapist
        description:
          type: string
          description: The description for the role.
          example: Therapists have read-only access to the system. This should be used to give users basic access to clients and reservations.
        organisation_id:
          type: string
          description: The id of the organisation this role belongs to.
          example: beddda88-947d-4bd8-8f0c-828b187f93b2
    schemas_Site:
      title: UserSiteRoleSite
      type: object
      description: A site object.
      additionalProperties: false
      required:
        - country_code
        - created_at
        - currency
        - external_id
        - frontend_subdomain
        - id
        - is_read_only
        - locale
        - name
        - organisation_id
        - organisation_name
        - timezone
      properties:
        id:
          type: string
          description: The ID of the site.
          example: 00000000-0000-0000-0000-111111111111
        name:
          type: string
          description: The name of the site
          example: Top Spa
        frontend_subdomain:
          type: string
          description: The subdomain which this shop is accessible from on the .try.be domain.
          example: topspa
        currency:
          type: string
          description: The ISO-4217 currency code in lower case
          example: gbp
        timezone:
          type: string
          description: The timezone of the site
          example: Europe/London
        locale:
          type: string
          description: The default locale of the site
          example: en
        country_code:
          type: string
          nullable: true
          description: The country code of the site
          example: GB
        external_id:
          type: string
          nullable: true
          description: An external identifier for the site
          example: GBSPA1
        organisation_id:
          type: string
          description: The id of the organisation this site belongs to
          example: 00000000-0000-0000-0000-000000000000
        organisation_name:
          type: string
          description: The name of the organisation this site belongs to
          example: Palm Tree Group Ltd.
        is_read_only:
          type: boolean
          description: Whether this site is read only. Users can only view data on read only sites.
          example: true
        created_at:
          type: string
          format: date-time
          example: '2023-05-24 12:00:00'
          description: The date and time the site was created.
    schemas_Role:
      type: object
      title: Role
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the role.
        name:
          type: string
          description: The name of the role.
          example: Spa Manager
        description:
          type: string
          description: The description of the role.
          example: Allows access to settings for the assigned site.
          nullable: true
        permissions:
          type: array
          description: The permissions assigned to this role.
          nullable: true
          items:
            type: string
            example: clients.view
        is_org_role:
          type: boolean
          description: Whether this role is organisation-level. Other permissions are applied at the Site level.
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this role relates to
      required:
        - id
        - name
        - description
        - permissions
        - is_org_role
        - organisation_id
    Permission:
      type: object
      title: Permission
      additionalProperties: false
      properties:
        name:
          type: string
          description: The name of the permission.
          example: clients.view
      required:
        - name
    EvaluationPeriod:
      type: string
      enum:
        - weekly
        - bi_weekly
        - monthly
    DayOfWeek:
      type: string
      description: A day of the week.
      enum:
        - sunday
        - monday
        - tuesday
        - wednesday
        - thursday
        - friday
        - saturday
      example: monday
    CommissionRateType:
      type: string
      description: |
        Whether a rate pays a proportion of the item's value or a fixed
        amount per item. `percentage` (the default) pays `percentage`
        percent of the item's (optionally discounted) value; `flat` pays
        the fixed `flat_amount` once per item, split across a `performed`
        item's practitioners the same way a percentage rate is.
      enum:
        - percentage
        - flat
      example: percentage
    CommissionAttribution:
      type: string
      description: |
        Which side of a sale a commission rate rewards. `performed` pays the
        practitioner who delivered the service or booking; `sold` pays
        whoever is recorded as the `sold_by` attribution on the basket item
        (a `Practitioner` or a plain `User`), such as a front-of-house
        staff member who upsold a retail product.
      enum:
        - performed
        - sold
      example: performed
    OfferingSetSummary:
      type: object
      title: OfferingSetSummary
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the offering set.
        name:
          type: string
          description: The name of the offering set.
      required:
        - id
        - name
    CommissionRate:
      type: object
      title: CommissionRate
      additionalProperties: false
      properties:
        name:
          type: string
          description: The name of the rate.
          example: Standard rate
          nullable: true
        rate_type:
          allOf:
            - $ref: '#/components/schemas/CommissionRateType'
            - description: |
                Whether this rate pays a `percentage` of the item's value or
                a `flat_amount` per item. Defaults to `percentage` when not
                set, including for rates persisted before flat rates were
                introduced.
              type: string
              nullable: true
              default: percentage
        percentage:
          type: number
          description: |
            The commission percentage to apply. Populated only when
            `rate_type` is `percentage`; `null` for a `flat` rate.
          example: 10
          nullable: true
        flat_amount:
          type: integer
          description: |
            The fixed commission amount to pay per item, in pence. Populated
            only when `rate_type` is `flat`; `null` for a `percentage` rate.
          example: 500
          nullable: true
        calculation_basis:
          type: string
          description: Whether the commission is calculated on the price before or after discount.
          enum:
            - before_discount
            - after_discount
        attribution:
          allOf:
            - $ref: '#/components/schemas/CommissionAttribution'
            - description: |
                Which side of the sale this rate rewards. Defaults to
                `performed` (the practitioner who delivered the service)
                when not set; `sold` rewards the basket item's `sold_by`
                attribution instead.
              type: string
              nullable: true
              default: performed
        offerings:
          type: array
          description: The specific offerings this rate applies to. An empty array means the rate applies to all offerings.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        offering_sets:
          type: array
          description: The offering sets this rate applies to.
          items:
            $ref: '#/components/schemas/OfferingSetSummary'
        threshold_amount:
          type: integer
          description: The minimum revenue threshold (in pence) that must be reached before this rate applies.
          example: 100000
          nullable: true
        evaluation_period:
          allOf:
            - $ref: '#/components/schemas/EvaluationPeriod'
            - description: Overrides the package's default evaluation period for this rate.
              type: string
              nullable: true
        valid_from:
          type: string
          format: date
          description: The date from which this rate is valid.
          nullable: true
        valid_to:
          type: string
          format: date
          description: The date until which this rate is valid.
          nullable: true
      required:
        - name
        - rate_type
        - percentage
        - flat_amount
        - calculation_basis
        - attribution
        - offerings
        - offering_sets
        - threshold_amount
        - evaluation_period
        - valid_from
        - valid_to
    CommissionPackage:
      type: object
      title: CommissionPackage
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the commission package.
        name:
          type: string
          description: The name of the commission package.
          example: Senior Therapist Package
        default_evaluation_period:
          allOf:
            - $ref: '#/components/schemas/EvaluationPeriod'
            - description: The default period over which commission is evaluated.
        week_starts_on:
          allOf:
            - $ref: '#/components/schemas/DayOfWeek'
            - description: |
                The day a `weekly` or `bi_weekly` evaluation period starts
                on. Defaults to `monday` when not set.
              type: string
              nullable: true
        requested_surcharge_percentage:
          type: number
          description: An optional surcharge percentage applied to requested practitioner bookings.
          example: 5
          nullable: true
        rates:
          type: array
          description: The commission rates defined in this package.
          items:
            $ref: '#/components/schemas/CommissionRate'
        site_id:
          type: string
          format: mongo-id
          description: The ID of the site this package belongs to.
        organisation_id:
          type: string
          format: mongo-id
          description: The ID of the organisation this package belongs to.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - name
        - default_evaluation_period
        - week_starts_on
        - requested_surcharge_percentage
        - rates
        - site_id
        - organisation_id
        - created_at
        - updated_at
    CreateCommissionPackageRate:
      type: object
      title: CreateCommissionPackageRate
      additionalProperties: false
      properties:
        name:
          type: string
          description: The name of the rate.
          example: Standard rate
          nullable: true
        rate_type:
          allOf:
            - $ref: '#/components/schemas/CommissionRateType'
            - description: |
                Whether this rate pays a `percentage` of the item's value or
                a `flat_amount` per item. Omit or send `null` to default to
                `percentage`.
              type: string
              nullable: true
              default: percentage
        percentage:
          type: number
          description: |
            The commission percentage to apply. Required unless `rate_type`
            is `flat`.
          example: 10
          nullable: true
        flat_amount:
          type: integer
          description: |
            The fixed commission amount to pay per item, in pence. Required
            when `rate_type` is `flat`.
          example: 500
          nullable: true
        calculation_basis:
          type: string
          description: Whether the commission is calculated on the price before or after discount.
          enum:
            - before_discount
            - after_discount
        attribution:
          allOf:
            - $ref: '#/components/schemas/CommissionAttribution'
            - description: |
                Which side of the sale this rate rewards. Omit or send
                `null` to default to `performed`.
              type: string
              nullable: true
              default: performed
        offerings:
          type: array
          description: The specific offerings this rate applies to.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        offering_set_ids:
          type: array
          description: IDs of offering sets this rate applies to.
          items:
            type: string
            format: mongo-id
        threshold_amount:
          type: integer
          description: The minimum revenue threshold (in pence) that must be reached before this rate applies.
          example: 100000
          nullable: true
        evaluation_period:
          allOf:
            - $ref: '#/components/schemas/EvaluationPeriod'
            - description: Overrides the package's default evaluation period for this rate.
              type: string
              nullable: true
        valid_from:
          type: string
          format: date
          description: The date from which this rate is valid.
          nullable: true
        valid_to:
          type: string
          format: date
          description: The date until which this rate is valid.
          nullable: true
      required:
        - calculation_basis
    UpdateCommissionPackage-content-application~1json-schema:
      type: object
      title: UpdateCommissionPackage
      additionalProperties: false
      properties:
        name:
          type: string
          description: |
            Display name of the commission package, shown in the
            admin UI when assigning packages to practitioners and on
            commission reports. Pick a name that summarises the
            package's rate structure. 1-120 characters.
          example: Senior Therapist Package
        default_evaluation_period:
          description: |
            The default period over which commission earned under this
            package is aggregated and paid out. Determines whether
            targets and tiers reset weekly, monthly, etc. Accepts the
            `EvaluationPeriod` enum values.
          allOf:
            - $ref: '#/components/schemas/EvaluationPeriod'
        week_starts_on:
          description: |
            The day a `weekly` or `bi_weekly` evaluation period
            starts on. Omit or send `null` to default to `monday`.
          allOf:
            - $ref: '#/components/schemas/DayOfWeek'
            - type: string
              nullable: true
              example: monday
        requested_surcharge_percentage:
          type: number
          description: An optional surcharge percentage applied to requested practitioner bookings.
          example: 5
          nullable: true
        rates:
          type: array
          description: The commission rates for this package.
          items:
            $ref: '#/components/schemas/CreateCommissionPackageRate'
    UserCommissionAssignment:
      type: object
      title: UserCommissionAssignment
      description: |
        Assigns a `CommissionPackage` to a plain `User` at a specific site,
        mirroring the `commission_package_id` field on `Practitioner` for
        staff who aren't modelled as practitioners (e.g. front-of-house
        staff earning commission under a `sold` attribution rate).
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The unique identifier of the assignment.
        user_id:
          type: string
          format: uuid
          description: The ID of the `User` this commission package is assigned to.
        site_id:
          type: string
          format: mongo-id
          description: The ID of the site this assignment applies to.
        commission_package_id:
          type: string
          format: mongo-id
          description: The ID of the `CommissionPackage` assigned to the user.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - user_id
        - site_id
        - commission_package_id
        - created_at
        - updated_at
    OfferingSet:
      type: object
      title: OfferingSet
      additionalProperties: false
      properties:
        id:
          type: string
          format: mongo-id
          description: The ID of the offering set.
        name:
          type: string
          description: The name of the offering set.
          example: Massage treatments
        offerings:
          type: array
          description: The offerings that belong to this set.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
        site_id:
          type: string
          format: mongo-id
          description: The ID of the site this offering set belongs to.
        organisation_id:
          type: string
          format: mongo-id
          description: The ID of the organisation this offering set belongs to.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - name
        - offerings
        - site_id
        - organisation_id
        - created_at
        - updated_at
    UpdateOfferingSet-content-application~1json-schema:
      type: object
      title: UpdateOfferingSet
      additionalProperties: false
      properties:
        name:
          type: string
          description: |
            Display name of the offering set, shown in the admin UI
            when picking a set to apply (e.g. as a coupon restriction
            or to scope a commission rate). Offering sets are reusable
            groupings of treatments, classes, or products.
            1-120 characters.
          example: Massage treatments
        offerings:
          type: array
          description: The offerings that belong to this set.
          items:
            $ref: '#/components/schemas/OfferingIdentifier'
    AreaBookingSlot:
      title: AreaBookingSlot
      type: object
      additionalProperties: false
      description: |
        A potential start time for an `AreaBookingType`, including its
        pricing and availability metadata.
      properties:
        start_time:
          type: string
          format: date-time
          description: The start date and time of the slot.
          example: '2026-06-12T10:00:00+01:00'
        end_time:
          type: string
          format: date-time
          description: The end date and time of the slot.
          example: '2026-06-12T11:30:00+01:00'
        duration:
          type: integer
          description: The duration of the slot in minutes.
          example: 90
        area_ids:
          type: array
          description: The IDs of the areas that could serve this slot.
          items:
            type: string
            format: mongo-id
        total_quantity:
          type: integer
          description: |
            The total number of bookings that could be made at this start
            time if every eligible area were free.
          example: 4
        quantity_available:
          type: integer
          description: The number of bookings currently available at this start time.
          example: 2
        price:
          type: integer
          description: The price of a single booking at this slot, in the smallest currency unit.
          example: 4500
        currency:
          type: string
          description: The ISO-4217 currency code of the price.
          example: gbp
        is_available:
          type: boolean
          description: Whether the slot can currently be booked.
        no_availability_reason:
          type: string
          nullable: true
          description: A reason code for the slot having no availability, if applicable.
          enum:
            - time_passed
            - date_passed
            - no_longer_bookable
            - not_yet_bookable
            - no_areas_available
            - start_time_not_allowed
            - invalid_offering_settings
            - not_offered_on_date
        no_availability_message:
          type: string
          nullable: true
          description: A user-friendly reason for the slot having no availability, if applicable.
          example: No matching areas are available at this time.
        bookable_from:
          type: string
          format: date-time
          nullable: true
          description: The earliest date and time that this slot may be booked, if applicable.
        bookable_to:
          type: string
          format: date-time
          nullable: true
          description: The date and time after which this slot may not be booked, if applicable.
      required:
        - start_time
        - end_time
        - duration
        - area_ids
        - total_quantity
        - quantity_available
        - price
        - currency
        - is_available
        - bookable_from
        - bookable_to
    AvailabilityWindow:
      title: AvailabilityWindow
      type: object
      additionalProperties: true
      description: A contiguous start/end period during which a resource is available.
      properties:
        start_time:
          type: string
          format: date-time
          description: The inclusive start of the window.
        end_time:
          type: string
          format: date-time
          description: The exclusive end of the window.
      required:
        - start_time
        - end_time
    schemas_OfferingSummary:
      title: OfferingSummary
      type: object
      additionalProperties: false
      nullable: true
      description: |
        Summary information about the offering the request was scoped to.
        Null when no offering was supplied.
      properties:
        id:
          type: string
          format: object-id
          description: The offering identifier.
        offering_type:
          type: string
          description: The offering's type discriminator.
          enum:
            - appointment
            - area_booking
            - session
            - course
            - product
            - package
            - voucher
        name:
          type: string
          description: The human-readable offering name.
        duration:
          type: integer
          nullable: true
          description: The offering duration in minutes.
        end_buffer:
          type: integer
          nullable: true
          description: |
            The minutes of buffer that should be reserved at the end of
            each booking.
        min_advance_bookings_interval:
          type: integer
          nullable: true
          description: |
            The minimum number of minutes ahead of the start time that the
            offering can be booked.
        max_advance_bookings_interval:
          type: integer
          nullable: true
          description: |
            The maximum number of minutes ahead of the start time that the
            offering can be booked.
        start_time_interval:
          type: integer
          nullable: true
          description: |
            The interval, in minutes, at which start times are offered
            (e.g. every 15 minutes).
      required:
        - id
        - offering_type
        - name
    CalendarAvailability:
      title: CalendarAvailability
      type: object
      additionalProperties: true
      nullable: true
      description: |
        The offering's day-level availability summary as it would appear on
        the booking calendar (e.g. available/unavailable/closed).
      properties:
        date:
          type: string
          format: date
          description: The date this availability summary applies to.
        available:
          type: boolean
          description: Whether the offering can be booked on the date.
      required:
        - date
        - available
    ScheduledSlot:
      title: ScheduledSlot
      type: object
      additionalProperties: true
      description: A discrete bookable slot generated from the offering's schedule.
      properties:
        start_time:
          type: string
          format: date-time
        end_time:
          type: string
          format: date-time
      required:
        - start_time
        - end_time
    schemas_RoomSummary:
      title: RoomSummary
      type: object
      additionalProperties: true
      description: A reduced summary of a `Room`.
      properties:
        id:
          type: string
          format: object-id
        name:
          type: string
      required:
        - id
        - name
    RoomAvailability:
      title: RoomAvailability
      type: object
      additionalProperties: false
      description: A single room together with its availability state.
      properties:
        room:
          $ref: '#/components/schemas/schemas_RoomSummary'
        availability_rules:
          type: array
          description: The room's configured availability rules for the date.
          items:
            $ref: '#/components/schemas/AvailabilityWindow'
        scheduled_slots:
          type: array
          description: The room's scheduled availability windows for the date.
          items:
            $ref: '#/components/schemas/AvailabilityWindow'
      required:
        - room
        - availability_rules
        - scheduled_slots
    schemas_PractitionerSummary-2:
      title: PractitionerSummary
      type: object
      additionalProperties: true
      description: A reduced summary of a `Practitioner`.
      properties:
        id:
          type: string
          format: object-id
        name:
          type: string
      required:
        - id
        - name
    PractitionerAvailability:
      title: PractitionerAvailability
      type: object
      additionalProperties: false
      description: A practitioner together with their availability and restrictions.
      properties:
        practitioner:
          $ref: '#/components/schemas/schemas_PractitionerSummary-2'
        availability_rules:
          type: array
          description: The practitioner's configured availability rules for the date.
          items:
            $ref: '#/components/schemas/AvailabilityWindow'
        scheduled_slots:
          type: array
          description: The practitioner's scheduled availability windows for the date.
          items:
            $ref: '#/components/schemas/AvailabilityWindow'
        restrictions:
          type: array
          description: |
            Practitioner-specific restrictions that apply to the requested
            offering on the date (e.g. maximum bookings, maximum duration).
          items:
            type: object
            additionalProperties: true
      required:
        - practitioner
        - availability_rules
        - scheduled_slots
        - restrictions
    schemas_EquipmentSummary:
      title: EquipmentSummary
      type: object
      additionalProperties: true
      description: A reduced summary of an `Equipment` resource.
      properties:
        id:
          type: string
          format: object-id
        name:
          type: string
      required:
        - id
        - name
    EquipmentAvailability:
      title: EquipmentAvailability
      type: object
      additionalProperties: false
      description: A piece of equipment together with its summary.
      properties:
        equipment:
          $ref: '#/components/schemas/schemas_EquipmentSummary'
      required:
        - equipment
    OccupiedPeriod:
      title: OccupiedPeriod
      type: object
      additionalProperties: true
      description: |
        A window during the day that is already occupied by an existing
        booking, hold or block. The shape mirrors `OccupiedPeriodResource`
        in the API.
      properties:
        start_time:
          type: string
          format: date-time
        end_time:
          type: string
          format: date-time
        practitioner_ids:
          type: array
          items:
            type: string
            format: object-id
          description: The practitioners occupied by the booking, if any.
        room_id:
          type: string
          format: object-id
          nullable: true
          description: The room occupied by the booking, if any.
      required:
        - start_time
        - end_time
    AvailabilityDetails:
      title: AvailabilityDetails
      type: object
      additionalProperties: false
      description: |
        A point-in-time snapshot of every resource that influences
        availability for a single site/date (and optionally a single
        offering). The Trybe calendar uses this payload to render the
        day view and to explain why a particular slot is or isn't
        bookable.
      properties:
        opening_hours:
          type: array
          description: The site's opening-hour windows for the requested date.
          items:
            $ref: '#/components/schemas/AvailabilityWindow'
        offering:
          $ref: '#/components/schemas/schemas_OfferingSummary'
        calendar_availability:
          $ref: '#/components/schemas/CalendarAvailability'
        scheduled_availability:
          type: array
          nullable: true
          description: |
            The combined availability windows derived from practitioner,
            room and equipment schedules for the offering. Only populated
            when `offering_id` is an appointment type.
          items:
            $ref: '#/components/schemas/AvailabilityWindow'
        scheduled_slots:
          type: array
          nullable: true
          description: |
            Discrete bookable slots generated from the scheduled
            availability for the offering. Only populated when
            `offering_id` is an appointment type.
          items:
            $ref: '#/components/schemas/ScheduledSlot'
        rooms:
          type: array
          description: |
            The rooms relevant to the request. When an offering is supplied,
            only rooms eligible for that offering are returned.
          items:
            $ref: '#/components/schemas/RoomAvailability'
        practitioners:
          type: array
          description: |
            The practitioners relevant to the request. When an offering is
            supplied, only practitioners eligible for that offering are
            returned.
          items:
            $ref: '#/components/schemas/PractitionerAvailability'
        equipment:
          type: array
          description: |
            The equipment items relevant to the request. When an offering
            is supplied, only equipment associated with the offering is
            returned.
          items:
            $ref: '#/components/schemas/EquipmentAvailability'
        occupied_periods:
          type: array
          description: |
            The periods within the day that are already occupied by an
            existing booking, hold, or block. Use these to render unavailable
            regions on the calendar.
          items:
            $ref: '#/components/schemas/OccupiedPeriod'
      required:
        - opening_hours
        - rooms
        - practitioners
        - equipment
        - occupied_periods
    AvailabilityDetailsResponse:
      title: AvailabilityDetailsResponse
      type: object
      additionalProperties: false
      properties:
        data:
          $ref: '#/components/schemas/AvailabilityDetails'
      required:
        - data
    AppointmentTag:
      title: AppointmentTag
      type: object
      description: |
        A tag that can be applied to appointment types within an
        organisation. Appointment tags are typically used to group similar
        treatments for reporting, search filters, or storefront navigation
        (e.g. "Express", "Couples", "Signature"). Tags belong to a single
        organisation and are visible across every site under that
        organisation.
      additionalProperties: false
      required:
        - id
        - name
        - organisation_id
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the appointment tag.
          example: 6630f7a8e1a4c2b1d4d5e7c1
        name:
          type: string
          description: |
            Display name of the tag, shown to staff in the admin UI and used
            when grouping appointment types in reports. 1-120 characters;
            must not contain HTML.
          example: Signature
        organisation_id:
          type: string
          format: uuid
          description: |
            The identifier of the organisation that owns the tag. Every
            appointment tag is scoped to exactly one organisation and is
            visible to every site under that organisation.
          example: 65a0c2e5b3a7d2f8c1d4e7b9
    AdyenFeesReportRow:
      type: object
      title: AdyenFeesReportRow
      additionalProperties: false
      description: |
        A single row in the Adyen fees report. Each row represents one
        captured Adyen payment, with the platform fees that Adyen charged
        broken out into their component parts. All monetary amounts are
        integers in the minor unit of `currency` (for example, pence for
        `gbp`).
      properties:
        id:
          type: string
          format: mongo-id
          description: The Trybe ID of the underlying `Payment`.
          example: 5f8a1b2c3d4e5f6a7b8c9d0e
        psp_ref:
          type: string
          nullable: true
          description: |
            The Adyen PSP (payment service provider) reference returned at
            authorisation. This is the same identifier shown in the Adyen
            Customer Area and can be used to look the transaction up there.
          example: 853599611111111A
        details_source:
          type: string
          nullable: true
          description: |
            Indicates how the payment details were captured (for example,
            `ecom` for a web checkout or `pos` for an in-person terminal).
          example: ecom
        card_brand:
          type: string
          nullable: true
          description: The brand of the card used for the payment.
          example: visa
        card_country:
          type: string
          nullable: true
          description: |
            The ISO 3166-1 alpha-2 country code of the card's issuing country.
          example: GB
        amount:
          type: integer
          description: The captured amount of the payment.
          example: 12500
        commission:
          type: integer
          description: The commission portion of the Adyen fees, in minor units.
          example: 12
        markup_fee:
          type: integer
          description: The markup portion of the Adyen fees, in minor units.
          example: 8
        scheme_fee:
          type: integer
          description: |
            The scheme fee (e.g. Visa or Mastercard network fee) portion of
            the Adyen fees, in minor units.
          example: 4
        interchange_fee:
          type: integer
          description: |
            The interchange fee portion of the Adyen fees paid to the issuing
            bank, in minor units.
          example: 30
        processing_fee:
          type: integer
          description: The processing fee portion of the Adyen fees, in minor units.
          example: 10
        total_fees:
          type: integer
          description: |
            The total Adyen fees deducted from this payment, in minor units.
            This is the sum of `commission`, `markup_fee`, `scheme_fee`,
            `interchange_fee` and `processing_fee`.
          example: 64
        application_fee:
          type: integer
          description: |
            The Trybe application fee charged on top of the Adyen fees, in
            minor units.
          example: 50
        currency:
          type: string
          description: |
            The currency of the payment. See [Supported Currencies](/endpoints/Meta#metaSupportedCurrencies)
            for the list of supported currency codes.
          example: gbp
        paid_at:
          type: string
          format: date-time
          description: The date and time the payment was captured.
          example: '2025-04-12T14:35:22+01:00'
        site_id:
          type: string
          format: uuid
          description: The ID of the `Site` the payment was made against.
        site_name:
          type: string
          description: The human-readable name of the `Site`.
          example: Trybe Spa London
      required:
        - id
        - psp_ref
        - details_source
        - card_brand
        - card_country
        - amount
        - commission
        - markup_fee
        - scheme_fee
        - interchange_fee
        - processing_fee
        - total_fees
        - application_fee
        - currency
        - paid_at
        - site_id
        - site_name
    ListAdyenFeesReportResponse:
      title: ListAdyenFeesReportResponse
      type: object
      additionalProperties: false
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AdyenFeesReportRow'
      required:
        - data
    OrganisationLabel:
      title: OrganisationLabel
      type: object
      description: |
        A coloured label that can be attached to records (e.g. customers,
        bookings, orders) to highlight or categorise them in the admin UI.
        Labels belong to a single organisation and can optionally be
        restricted to a subset of the organisation's sites — staff only see
        labels whose `site_ids` intersect with the site they are working
        against.
      additionalProperties: false
      required:
        - id
        - name
        - color
        - organisation_id
        - site_ids
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the label.
          example: 6630f7a8e1a4c2b1d4d5e7c1
        name:
          type: string
          maxLength: 40
          description: |
            Display name of the label, shown next to the records it is
            attached to in the admin UI. 1-40 characters; must not contain
            HTML.
          example: VIP
        color:
          type: string
          pattern: ^#[0-9a-f]{6}$
          description: |
            Hex colour used to render the label in the admin UI, including
            the leading `#`. Lower-case hexadecimal; must match
            `#rrggbb`. When unset on create, defaults to `#f1f1f1`.
          example: '#ff5733'
        organisation_id:
          type: string
          format: uuid
          description: |
            Identifier of the organisation that owns the label. Every label
            is scoped to exactly one organisation.
          example: 65a0c2e5b3a7d2f8c1d4e7b9
        site_ids:
          type: array
          description: |
            Identifiers of the sites within the organisation that can see
            and apply this label. Empty array means the label is visible
            to every site under the organisation.
          items:
            type: string
            format: uuid
          example:
            - 65a0c2e5b3a7d2f8c1d4e7ba
            - 65a0c2e5b3a7d2f8c1d4e7bb
    OrganisationRevenueCentre:
      type: object
      title: OrganisationRevenueCentre
      description: |
        An accounting category against which revenue can be recorded at an
        organisation-wide level. Revenue centres group sales for tax and
        reporting purposes (e.g. Spa, Retail, Food & Beverage). Trybe ships
        with a small set of system revenue centres that cannot be deleted;
        operators can add as many custom ones as they need.
      additionalProperties: false
      required:
        - id
        - key
        - name
        - tax_percent
        - tax_configuration
        - is_required
      properties:
        id:
          type: string
          description: |
            The identifier of the revenue centre. System revenue centres
            use stable, lower-case slugs (`spa`, `deposit`, ...); custom
            ones are issued when the centre is created.
          example: spa
        key:
          type: string
          description: |
            A stable key for the revenue centre, used when looking it up
            from external integrations. For most centres this matches the
            `id`.
          example: spa
        name:
          type: string
          description: |
            Display name of the revenue centre, shown in the admin UI and
            on financial reports.
          example: Spa
        tax_percent:
          type: number
          nullable: true
          description: |
            The percentage of tax applied to sales recorded against this
            revenue centre when no per-line tax configuration overrides it.
          example: 20
        tax_configuration:
          $ref: '#/components/schemas/TaxConfigurationSummary'
          nullable: true
        is_required:
          type: boolean
          description: |
            Whether this revenue centre is required by Trybe and cannot be
            deleted (e.g. `spa`, `deposit`, membership fees).
          example: true
    CreateOrganisationRevenueCentre:
      type: object
      title: CreateOrganisationRevenueCentre
      additionalProperties: false
      required:
        - name
      properties:
        key:
          type: string
          description: |
            Optional stable key for the new revenue centre. Used when
            looking the centre up from external integrations. Defaults to a
            slugified form of `name` when omitted.
          example: retail
        name:
          type: string
          description: |
            Display name of the revenue centre, shown in the admin UI and
            on financial reports.
          example: Retail
        tax_percent:
          type: number
          nullable: true
          description: |
            The percentage of tax to apply to sales recorded against this
            revenue centre when no per-line tax configuration overrides it.
          example: 20
    properties-key:
      type: string
      description: |
        Optional stable key for the new revenue centre. Used when
        looking the centre up from external integrations. Defaults to a
        slugified form of `name` when omitted.
      example: retail
    CreateOrganisationRevenueCentre-properties-name:
      type: string
      description: |
        Display name of the revenue centre, shown in the admin UI and
        on financial reports.
      example: Retail
    properties-tax_percent:
      type: number
      nullable: true
      description: |
        The percentage of tax to apply to sales recorded against this
        revenue centre when no per-line tax configuration overrides it.
      example: 20
    UpdateOrganisationRevenueCentre:
      type: object
      title: UpdateOrganisationRevenueCentre
      additionalProperties: false
      required:
        - name
      properties:
        key:
          $ref: '#/components/schemas/properties-key'
        name:
          $ref: '#/components/schemas/CreateOrganisationRevenueCentre-properties-name'
        tax_percent:
          $ref: '#/components/schemas/properties-tax_percent'
    schemas_SalesChannel-2:
      title: SalesChannel
      type: object
      description: |
        A sales channel records the source of a sale (e.g. "Front Desk",
        "Phone", "Website", "Partner App"). Channels are scoped to an
        organisation and are selectable on orders, appointments, and other
        revenue-bearing records to support source-level reporting and
        reconciliation. Trybe ships with a small set of system channels and
        operators can add as many custom channels as they need.
      additionalProperties: false
      required:
        - id
        - name
        - organisation_id
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the sales channel.
          example: 6630f7a8e1a4c2b1d4d5e7c1
        name:
          type: string
          description: |
            Display name of the sales channel, shown in pickers across the
            admin UI and on reports that break revenue down by channel.
          example: Front Desk
        organisation_id:
          type: string
          format: uuid
          description: |
            Identifier of the organisation that owns the sales channel.
            Every channel is scoped to exactly one organisation.
          example: 65a0c2e5b3a7d2f8c1d4e7b9
    schemas_BookableAreaSummary:
      type: object
      title: BookableAreaSummary
      additionalProperties: true
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: object-id
        name:
          type: string
          example: Pool
    BookableAreaOccupancyRow:
      type: object
      title: BookableAreaOccupancyRow
      additionalProperties: true
      required:
        - bookable_area
        - bookable_mins
        - blocked_mins
        - booked_mins
      properties:
        bookable_area:
          $ref: '#/components/schemas/schemas_BookableAreaSummary'
        bookable_mins:
          type: integer
        blocked_mins:
          type: integer
        booked_mins:
          type: integer
    BookableAreaOccupancyTotals:
      type: object
      title: BookableAreaOccupancyTotals
      additionalProperties: false
      required:
        - bookable_mins
        - blocked_mins
        - booked_mins
      properties:
        bookable_mins:
          type: integer
        blocked_mins:
          type: integer
        booked_mins:
          type: integer
    BookableAreaOccupancyResponse:
      type: object
      title: BookableAreaOccupancyResponse
      additionalProperties: false
      description: |
        For each bookable area at the site, the number of bookable / blocked / booked minutes
        across the requested date range.
      required:
        - data
        - totals
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/BookableAreaOccupancyRow'
        totals:
          $ref: '#/components/schemas/BookableAreaOccupancyTotals'
    TableReportCell:
      type: object
      title: TableReportCell
      additionalProperties: true
      description: |
        A single cell in a `TableReport`. `format` is `th` for header cells and `td` for body cells.
        `value` carries the displayed content. Additional formatting hints (such as `colspan` or a
        pre-formatted display string) may be present depending on the report.
      required:
        - format
      properties:
        format:
          type: string
          enum:
            - th
            - td
          description: The cell type — `th` for header rows, `td` for body rows.
        value:
          description: The cell's displayed value.
          oneOf:
            - type: string
            - type: number
            - type: integer
            - type: boolean
    TableReportRow:
      type: object
      title: TableReportRow
      additionalProperties: false
      required:
        - cells
      properties:
        cells:
          type: array
          description: The cells of the row, in display order.
          items:
            $ref: '#/components/schemas/TableReportCell'
    TableReport:
      type: object
      title: TableReport
      additionalProperties: false
      description: |
        A row-and-column representation of a report. The first row is the header (`format: th`)
        and subsequent rows are body cells (`format: td`). Used by aggregate / summary reports
        that are intended for display rather than programmatic consumption.
      required:
        - rows
      properties:
        rows:
          type: array
          description: The rows of the table, in display order.
          items:
            $ref: '#/components/schemas/TableReportRow'
    CancellationsAndNoShowsResponse:
      type: object
      title: CancellationsAndNoShowsResponse
      additionalProperties: false
      description: |
        Display-formatted aggregate of cancelled and no-show baskets, split into a `data` table
        of by-status rows and a single-row `totals` table. For programmatic access to the same
        underlying numbers, prefer the v2 endpoint.
      required:
        - data
        - totals
      properties:
        data:
          $ref: '#/components/schemas/TableReport'
        totals:
          $ref: '#/components/schemas/TableReport'
    CancellationStatusBucket:
      type: object
      title: CancellationStatusBucket
      additionalProperties: false
      required:
        - name
        - count
        - total_net
        - total_gross
      properties:
        name:
          type: string
          description: A human-readable label for the bucket (e.g. "Cancelled", "No show", "Totals").
          example: Cancelled
        count:
          type: integer
          description: The number of baskets in this bucket.
          example: 12
        total_net:
          type: integer
          description: The combined net total for this bucket, in minor units.
          example: 90000
        total_gross:
          type: integer
          description: The combined gross total for this bucket, in minor units.
          example: 108000
    CancellationsAndNoShowsV2Response:
      type: object
      title: CancellationsAndNoShowsV2Response
      additionalProperties: false
      description: |
        Programmatic JSON shape for the cancellations and no-shows report. Each bucket reports
        the number of baskets and net/gross total in minor units.
      required:
        - cancelled
        - no_shows
        - total
      properties:
        cancelled:
          $ref: '#/components/schemas/CancellationStatusBucket'
        no_shows:
          $ref: '#/components/schemas/CancellationStatusBucket'
        total:
          $ref: '#/components/schemas/CancellationStatusBucket'
    Charge:
      type: object
      title: Charge
      additionalProperties: false
      required:
        - id
        - charge_type
        - chargeable_type
        - chargeable_id
        - processor
        - processor_id
        - amount
        - currency
        - status
        - created_at
      properties:
        id:
          type: string
          format: object-id
          example: 60a8c0901d210625e3a87667
        charge_type:
          type: string
          description: The type of charge (e.g. `payment`, `refund`).
          example: payment
        chargeable_type:
          type: string
          description: The type of resource this charge applies to.
          example: order
          enum:
            - order
            - membership
            - ''
        order_ref:
          type: string
          nullable: true
          example: TRY03
        order_status:
          type: string
          nullable: true
          example: settled
        revenue_date:
          type: string
          nullable: true
          description: The revenue date assigned to the underlying basket, as `YYYY-MM-DD`.
          example: '2026-06-15'
        payout_date:
          type: string
          nullable: true
          description: The date Trybe payouts settled this charge.
          example: '2026-06-18'
        chargeable_id:
          type: string
          format: object-id
        customer_id:
          type: string
          nullable: true
        customer_name:
          type: string
          nullable: true
          example: Jane Doe
        processor:
          type: string
          example: adyen
        processor_type:
          type: string
          example: card
        processor_type_id:
          type: string
          nullable: true
        processor_id:
          type: string
          example: PSP_REF_123
        notes:
          type: string
          nullable: true
        amount:
          type: integer
          description: The charge amount, in minor units. Positive for payments, positive for refunds.
          example: 15000
        currency:
          type: string
          example: gbp
        status:
          type: string
          example: complete
        failure_reason:
          type: string
          nullable: true
        cardholder_name:
          type: string
          nullable: true
        card_brand:
          type: string
          nullable: true
        card_last4:
          type: string
          nullable: true
        application_fee:
          description: The application fee taken on this charge in minor units, or an empty string when not applicable.
          oneOf:
            - type: integer
            - type: string
        net_amount:
          type: integer
          description: The net amount of the charge after processor fees, in minor units.
        created_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
          nullable: true
    ChargeProcessorTotal:
      type: object
      title: ChargeProcessorTotal
      additionalProperties: true
      required:
        - processor
        - amount
      properties:
        processor:
          type: string
          example: adyen
        amount:
          type: integer
          example: 250000
    ChargeListResponse:
      type: object
      title: ChargeListResponse
      additionalProperties: false
      required:
        - data
        - meta
        - links
        - processor_totals
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Charge'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        processor_totals:
          type: array
          description: A per-processor net total for the charges matched by the filters.
          items:
            $ref: '#/components/schemas/ChargeProcessorTotal'
    CommissionReportRow:
      type: object
      title: CommissionReportRow
      additionalProperties: false
      required:
        - practitioner_id
        - practitioner_name
        - earner_id
        - earner_name
        - earner_type
        - commission_package_name
        - date_from
        - date_to
        - total_sales
        - total_commission
        - total_surcharge
        - total_gross_commission
        - item_count
        - currency
      properties:
        practitioner_id:
          type: string
          format: mongo-id
          description: |
            The unique identifier of the practitioner. Deprecated: kept for
            backwards compatibility and only populated when `earner_type`
            is `practitioner`. Prefer `earner_id`, which also covers rows
            earned by a plain `User` under a `sold` attribution rate.
          example: 60c72b2f9b1e8a001c8e4f1a
          nullable: true
          deprecated: true
        practitioner_name:
          type: string
          description: |
            The practitioner's name, or "Unknown" if their record has been
            removed. Deprecated: kept for backwards compatibility and only
            populated when `earner_type` is `practitioner`. Prefer
            `earner_name`.
          example: Sarah Smith
          nullable: true
          deprecated: true
        earner_id:
          type: string
          description: |
            The unique identifier of the entity that earned this
            commission — a `Practitioner` for a `performed` rate, or a
            `Practitioner` or `User` for a `sold` rate, depending on who
            is recorded as the basket item's `sold_by` attribution.
          example: 60c72b2f9b1e8a001c8e4f1a
        earner_name:
          type: string
          description: The earner's name, or "Unknown" if their record has been removed.
          example: Sarah Smith
        earner_type:
          type: string
          description: Discriminator indicating which underlying entity `earner_id` refers to.
          enum:
            - practitioner
            - user
          example: practitioner
        commission_package_name:
          type: string
          example: Standard Therapist Commission
        date_from:
          type: string
          format: date
        date_to:
          type: string
          format: date
        total_sales:
          type: integer
          description: The total qualifying sales for the period, in the site currency's minor unit.
          example: 45000
        total_commission:
          type: integer
          description: The net commission owed to the practitioner, in the site currency's minor unit.
          example: 4500
        total_surcharge:
          type: integer
          description: Any commission surcharge applied to the calculation, in the site currency's minor unit.
          example: 0
        total_gross_commission:
          type: integer
          description: The gross commission before any surcharges, in the site currency's minor unit.
          example: 4500
        item_count:
          type: integer
          description: The number of qualifying items in the period.
          example: 9
        currency:
          type: string
          example: gbp
    CommissionReportResponse:
      type: object
      title: CommissionReportResponse
      additionalProperties: false
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CommissionReportRow'
    CommissionBreakdownRow:
      type: object
      title: CommissionBreakdownRow
      additionalProperties: false
      required:
        - practitioner_id
        - practitioner_name
        - earner_id
        - earner_name
        - earner_type
        - attribution
        - period_from
        - period_to
        - basket_item_id
        - basket_id
        - order_ref
        - customer_name
        - offering_name
        - offering_type
        - item_date
        - item_price
        - item_total_cost
        - rate_type
        - rate_percentage
        - rate_flat_amount
        - commission_amount
        - surcharge_amount
        - total_commission
        - currency
      properties:
        practitioner_id:
          type: string
          format: object-id
          description: |
            The unique identifier of the practitioner. Deprecated: kept for
            backwards compatibility and only populated when `earner_type`
            is `practitioner`. Prefer `earner_id`, which also covers rows
            earned by a plain `User` under a `sold` attribution rate.
          nullable: true
          deprecated: true
        practitioner_name:
          type: string
          description: |
            The practitioner's name, or "Unknown" if their record has been
            removed. Deprecated: kept for backwards compatibility and only
            populated when `earner_type` is `practitioner`. Prefer
            `earner_name`.
          example: Sarah Smith
          nullable: true
          deprecated: true
        earner_id:
          type: string
          description: |
            The unique identifier of the entity that earned commission on
            this item — a `Practitioner` for a `performed` rate, or a
            `Practitioner` or `User` for a `sold` rate, depending on who
            is recorded as the basket item's `sold_by` attribution.
          example: 60c72b2f9b1e8a001c8e4f1a
        earner_name:
          type: string
          description: The earner's name, or "Unknown" if their record has been removed.
          example: Sarah Smith
        earner_type:
          type: string
          description: Discriminator indicating which underlying entity `earner_id` refers to.
          enum:
            - practitioner
            - user
          example: practitioner
        attribution:
          allOf:
            - $ref: '#/components/schemas/CommissionAttribution'
            - description: |
                Which side of the sale the commission rate applied to this
                item rewarded — the practitioner who performed the service,
                or whoever is recorded as the item's `sold_by` attribution.
              type: string
        period_from:
          type: string
          format: date
          nullable: true
          description: Start of the commission period this item falls within.
          example: '2026-06-01'
        period_to:
          type: string
          format: date
          nullable: true
          description: End of the commission period this item falls within.
          example: '2026-06-30'
        basket_item_id:
          type: string
          format: object-id
          description: The unique identifier of the basket item.
        basket_id:
          type: string
          format: object-id
          description: The unique identifier of the basket this item was in.
        order_ref:
          type: string
          description: The order reference for the order containing this item.
          example: TRY12
        customer_name:
          type: string
          nullable: true
          description: |
            The customer's name as it appeared on the basket when the
            commission was generated. `null` when the basket had no
            customer attached (e.g. a walk-in). Snapshotted at generation
            time so a later customer rename or removal doesn't alter
            historical rows.
          example: Ada Lovelace
        offering_name:
          type: string
          description: The name of the offering that was sold.
          example: Swedish Massage 60min
        offering_type:
          type: string
          description: The type of offering (e.g. `appointment`, `session`).
          example: appointment
        item_date:
          type: string
          format: date
          nullable: true
          description: The date the item took place.
          example: '2026-06-15'
        item_price:
          type: integer
          description: The price of the individual item, in the site currency's minor unit.
          example: 9000
        item_total_cost:
          type: integer
          description: The total cost of the item used as the commission base, in the site currency's minor unit.
          example: 9000
        rate_type:
          allOf:
            - $ref: '#/components/schemas/CommissionRateType'
            - description: Whether the rate applied to this item paid a `percentage` of its value or a `flat_amount` per item.
              type: string
        rate_percentage:
          type: number
          description: The commission rate percentage applied to this item. `null` when `rate_type` is `flat`.
          example: 10
          nullable: true
        rate_flat_amount:
          type: integer
          description: |
            The flat commission amount applied to this item, in the site
            currency's minor unit. `null` when `rate_type` is `percentage`.
          example: 500
          nullable: true
        commission_amount:
          type: integer
          description: The net commission earned on this item, in the site currency's minor unit.
          example: 900
        surcharge_amount:
          type: integer
          description: Any commission surcharge applied to this item, in the site currency's minor unit.
          example: 0
        total_commission:
          type: integer
          description: The total commission for this item including any surcharge, in the site currency's minor unit.
          example: 900
        currency:
          type: string
          example: gbp
    CommissionBreakdownResponse:
      type: object
      title: CommissionBreakdownResponse
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CommissionBreakdownRow'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    DailyRevenueStatsResponse:
      type: object
      title: DailyRevenueStatsResponse
      additionalProperties: true
      description: |
        A single-day revenue dashboard payload. Each top-level field is a numeric breakdown of
        the day's activity; all money values are integers in minor units. The exact shape of
        each sub-tree is intentionally loose to allow new metrics to be added without breaking
        consumers — only the top-level keys are guaranteed.
      required:
        - revenue_by_centre
        - payments_by_processor
        - operational_stats
        - orders
        - item_type_breakdown
        - top_items
      properties:
        revenue_by_centre:
          description: Revenue grouped by revenue centre for the day.
        payments_by_processor:
          description: Payments grouped by processor (Adyen, Stripe, cash, etc.).
        operational_stats:
          description: Headline operational counts (e.g. appointments, sessions).
        orders:
          description: Order totals for the day.
        item_type_breakdown:
          description: A breakdown by offering type.
        top_items:
          description: The top-selling items by net revenue.
    DailySalesStatsResponse:
      type: object
      title: DailySalesStatsResponse
      additionalProperties: true
      description: |
        A single-day sales dashboard payload — companion to
        [`/shop/reports/daily-revenue-stats`](/endpoints/Reports#getDailyRevenueStats). Includes
        payment / refund / membership breakdowns. All money values are integers in minor units;
        sub-tree shapes are intentionally loose so new metrics can be added without breaking
        consumers.
      required:
        - payments_by_processor
        - refunds
        - orders
        - order_stats
        - memberships
      properties:
        payments_by_processor:
          description: Payments grouped by processor (Adyen, Stripe, cash, etc.).
        refunds:
          description: Refund totals broken down by processor.
        orders:
          description: A sample of the day's orders.
        order_stats:
          description: Aggregate order counts and totals for the day.
        memberships:
          description: Membership-related sales counts for the day.
    DiscountUsageRow:
      type: object
      title: DiscountUsageRow
      additionalProperties: false
      required:
        - discount_type_id
        - discount_type_name
        - num_baskets
        - num_items
        - basket_discount_total
        - item_discount_total
        - discount_total
      properties:
        discount_type_id:
          type: string
          format: object-id
          example: 60a8c0901d210625e3a87667
        is_deleted:
          type: boolean
          description: Whether the discount type has been soft-deleted.
        site_id:
          type: string
          format: uuid
          nullable: true
        discount_type_name:
          type: string
          example: Member Discount
        discount_type_code:
          type: string
          nullable: true
          example: MEMBER10
        num_baskets:
          type: integer
          description: Number of baskets the discount was applied to.
        num_items:
          type: integer
          description: Number of basket items the discount was applied to.
        basket_discount_total:
          type: integer
          description: The total amount discounted at the basket level, in minor units.
        item_discount_total:
          type: integer
          description: The total amount discounted at the item level, in minor units.
        discount_total:
          type: integer
          description: The combined total of basket-level and item-level discount amounts, in minor units.
    DiscountUsageV2Response:
      type: object
      title: DiscountUsageV2Response
      additionalProperties: false
      required:
        - data
      properties:
        data:
          type: array
          description: One entry per discount type that was offered or applied in the filter range.
          items:
            $ref: '#/components/schemas/DiscountUsageRow'
    GeneralLedgerEntry:
      type: object
      title: GeneralLedgerEntry
      additionalProperties: true
      required:
        - date
        - type
        - description
      properties:
        date:
          type: string
          format: date-time
        type:
          type: string
          enum:
            - revenue
            - payment
            - refund
        revenue_centre:
          type: string
          nullable: true
        description:
          type: string
          example: Card payment
        amount:
          type: integer
          description: Total amount of the entry, in minor units. Negative for payments.
        gross_amount:
          type: integer
          description: Gross revenue amount, in minor units (revenue entries only).
        net_amount:
          type: integer
          description: Net revenue amount, in minor units (revenue entries only).
        tax_amount:
          type: integer
          description: Tax amount, in minor units (revenue entries only).
        meta:
          type: object
          title: GeneralLedgerEntryMeta
          additionalProperties: true
          description: |
            Contextual references for the ledger entry — e.g. `order_ref`, `basket_id`,
            `payment_id`, or `refund_id` depending on the entry type.
    GeneralLedgerResponse:
      type: array
      title: GeneralLedgerResponse
      description: |
        A chronologically-sorted general ledger combining basket revenue, payments, refunds and
        revenue reversals at a site over the requested period. Money fields are integers in
        minor units; the `meta` block accompanying the response carries the opening and
        closing balances.
      items:
        $ref: '#/components/schemas/GeneralLedgerEntry'
    ItemRevenueAllocation:
      type: object
      title: ItemRevenueAllocation
      additionalProperties: false
      required:
        - revenue_centre
        - gross_revenue
        - net_revenue
      properties:
        revenue_centre:
          type: string
          nullable: true
          example: spa
        gross_revenue:
          type: integer
          example: 15000
        net_revenue:
          type: integer
          example: 12500
    ItemRevenue:
      type: object
      title: ItemRevenue
      additionalProperties: false
      required:
        - id
        - basket_id
        - order_ref
        - offering_type
        - offering_id
        - offering_name
        - total_cost
        - net_total
        - gross_revenue
        - net_revenue
        - date
        - revenues
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the basket item.
          example: 60a8c0901d210625e3a87667
        basket_id:
          type: string
          format: object-id
          example: 60a8c0901d210625e3a87668
        order_ref:
          type: string
          example: TRY03
        offering_type:
          type: string
          example: appointment
        offering_id:
          type: string
          format: object-id
        offering_name:
          type: string
          example: 60 Minute Massage
        total_cost:
          type: integer
          description: The total cost of the item, in minor units.
          example: 15000
        net_total:
          type: integer
          description: The net total of the item after tax, in minor units.
          example: 12500
        gross_revenue:
          type: integer
          description: The sum of all gross revenue allocations on this item, in minor units.
        net_revenue:
          type: integer
          description: The sum of all net revenue allocations on this item, in minor units.
        date:
          type: string
          description: The earliest date the item takes place on, or an empty string if the item has no date.
          example: '2026-06-15'
        revenues:
          type: array
          description: Revenue allocations on this item, grouped by revenue centre.
          items:
            $ref: '#/components/schemas/ItemRevenueAllocation'
    ItemRevenuesMeta:
      type: object
      title: ItemRevenuesMeta
      additionalProperties: true
      required:
        - revenue_centres
      properties:
        revenue_centres:
          type: array
          description: Lookup of the revenue centres referenced in `data`.
          items:
            type: object
            title: ItemRevenuesMetaRevenueCentre
            additionalProperties: true
            required:
              - key
            properties:
              key:
                type: string
              name:
                type: string
    ItemRevenuesResponse:
      type: object
      title: ItemRevenuesResponse
      additionalProperties: false
      required:
        - data
        - meta
        - links
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/ItemRevenue'
        meta:
          $ref: '#/components/schemas/ItemRevenuesMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
    OccupancyOverviewBaskets:
      type: object
      title: OccupancyOverviewBaskets
      additionalProperties: true
      required:
        - num_baskets
      properties:
        num_baskets:
          type: integer
          example: 35
        num_booked_appointments:
          type: integer
          example: 22
        num_booked_sessions:
          type: integer
          example: 5
        num_booked_packages:
          type: integer
          example: 8
    OccupancyOverviewSessions:
      type: object
      title: OccupancyOverviewSessions
      additionalProperties: false
      required:
        - num_sessions
        - total_session_capacity
        - total_session_booked_customers
      properties:
        num_sessions:
          type: integer
          example: 6
        total_session_capacity:
          type: integer
          example: 60
        total_session_booked_customers:
          type: integer
          example: 32
    OccupancyOverviewBlockedTimes:
      type: object
      title: OccupancyOverviewBlockedTimes
      additionalProperties: false
      required:
        - num_blocked_times
        - total_mins
      properties:
        num_blocked_times:
          type: integer
        total_mins:
          type: integer
          description: The total number of minutes blocked off across the day.
    OccupancyOverviewPractitioners:
      type: object
      title: OccupancyOverviewPractitioners
      additionalProperties: true
      description: |
        Per-day roll-up of the practitioner occupancy report. Mirrors the shape of the same
        report at [`/shop/reports/practitioner-occupancy-by-date`](/endpoints/Reports#getPractitionerOccupancyByDateReport).
    OccupancyOverviewRooms:
      type: object
      title: OccupancyOverviewRooms
      additionalProperties: true
      description: |
        Per-day roll-up of room occupancy minutes. Mirrors the shape of the same report at
        [`/shop/reports/room-occupancy`](/endpoints/Reports#listRoomOccupancy).
    OccupancyOverviewDay:
      type: object
      title: OccupancyOverviewDay
      additionalProperties: true
      required:
        - date
        - baskets
        - sessions
        - blocked_times
        - practitioners
        - rooms
      properties:
        date:
          type: string
          format: date
        baskets:
          $ref: '#/components/schemas/OccupancyOverviewBaskets'
        sessions:
          $ref: '#/components/schemas/OccupancyOverviewSessions'
        blocked_times:
          $ref: '#/components/schemas/OccupancyOverviewBlockedTimes'
        practitioners:
          $ref: '#/components/schemas/OccupancyOverviewPractitioners'
        rooms:
          $ref: '#/components/schemas/OccupancyOverviewRooms'
    OccupancyOverviewResponse:
      type: object
      title: OccupancyOverviewResponse
      additionalProperties: false
      required:
        - data
      properties:
        data:
          type: array
          description: One entry per day in the requested range, in date order.
          items:
            $ref: '#/components/schemas/OccupancyOverviewDay'
    PayByLinkPayment:
      type: object
      title: PayByLinkPayment
      additionalProperties: false
      required:
        - id
        - status
        - order_ref
        - basket_id
        - customer_name
        - created_at
      properties:
        id:
          type: string
          format: object-id
          description: The charge ID.
        status:
          type: string
          description: The current status of the pay-by-link charge.
          example: pending
        order_ref:
          type: string
          example: TRY03
        basket_id:
          type: string
          format: object-id
          description: The ID of the basket the pay-by-link payment is collecting for.
        customer_name:
          type: string
          nullable: true
          example: Jane Doe
        revenue_date:
          type: string
          nullable: true
          description: The revenue date of the underlying basket, as `YYYY-MM-DD`.
        created_at:
          type: string
          format: date-time
        paid_at:
          type: string
          format: date-time
          nullable: true
          description: When the customer completed the payment. `null` until the charge has been collected.
    PayByLinkPaymentsResponse:
      type: object
      title: PayByLinkPaymentsResponse
      additionalProperties: false
      required:
        - data
        - meta
        - links
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PayByLinkPayment'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
    PractitionerUtilisationRow:
      type: object
      title: PractitionerUtilisationRow
      additionalProperties: true
      required:
        - practitioner_id
        - practitioner_name
      properties:
        practitioner_id:
          type: string
          format: object-id
          example: 60a8c0901d210625e3a87667
        practitioner_name:
          type: string
          example: Sarah Smith
        bookable_mins:
          type: integer
          description: Bookable minutes within the requested range.
          example: 2400
        appointment_mins:
          type: integer
          description: Minutes spent on appointments.
          example: 1500
        session_mins:
          type: integer
          description: Minutes spent on sessions.
          example: 200
        blocked_mins:
          type: integer
          description: Minutes blocked off and unavailable for bookings.
          example: 60
        net_revenue:
          type: integer
          description: Net revenue attributed to this practitioner, in minor units.
          example: 180000
    PractitionerUtilisationTotals:
      type: object
      title: PractitionerUtilisationTotals
      additionalProperties: true
      properties:
        bookable_mins:
          type: integer
        appointment_mins:
          type: integer
        session_mins:
          type: integer
        blocked_mins:
          type: integer
        net_revenue:
          type: integer
      required:
        - bookable_mins
        - appointment_mins
        - session_mins
        - blocked_mins
        - net_revenue
    PractitionerUtilisationMeta:
      type: object
      title: PractitionerUtilisationMeta
      additionalProperties: true
      required:
        - date_from
        - date_to
      properties:
        date_from:
          type: string
          format: date
        date_to:
          type: string
          format: date
    PractitionerUtilisationResponse:
      type: object
      title: PractitionerUtilisationResponse
      additionalProperties: false
      description: |
        For each practitioner, the number of minutes available vs. booked vs. blocked across
        the requested date range, along with attributed net revenue.
      required:
        - data
        - totals
        - meta
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PractitionerUtilisationRow'
        totals:
          $ref: '#/components/schemas/PractitionerUtilisationTotals'
        meta:
          $ref: '#/components/schemas/PractitionerUtilisationMeta'
    SalesChannelRevenueCentreSummary:
      type: object
      title: SalesChannelRevenueCentreSummary
      additionalProperties: false
      required:
        - revenue_centre
        - gross_revenue
        - net_revenue
      properties:
        revenue_centre:
          type: string
          nullable: true
          description: The key of the revenue centre.
          example: spa
        gross_revenue:
          type: integer
          example: 120000
        net_revenue:
          type: integer
          example: 100000
    OrderLabelRevenueSummary:
      type: object
      title: OrderLabelRevenueSummary
      additionalProperties: false
      required:
        - label_id
        - gross_revenue
        - net_revenue
        - revenue_centres
      properties:
        label_id:
          type: string
          format: object-id
          nullable: true
          description: The ID of the order label. `null` for baskets that had no labels applied.
          example: 69c128c05a210879a60ac1af
        label_name:
          type: string
          nullable: true
          example: VIP
        gross_revenue:
          type: integer
          example: 250000
        net_revenue:
          type: integer
          example: 208000
        revenue_centres:
          type: array
          items:
            $ref: '#/components/schemas/SalesChannelRevenueCentreSummary'
    RevenueByOrderLabelV2Meta:
      type: object
      title: RevenueByOrderLabelV2Meta
      additionalProperties: false
      required:
        - revenue_centres
      properties:
        revenue_centres:
          type: array
          items:
            $ref: '#/components/schemas/RevenueCentreSummary'
    RevenueByOrderLabelV2Response:
      type: object
      title: RevenueByOrderLabelV2Response
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          type: array
          description: One entry per order label that contributed revenue in the filter range.
          items:
            $ref: '#/components/schemas/OrderLabelRevenueSummary'
        meta:
          $ref: '#/components/schemas/RevenueByOrderLabelV2Meta'
    SalesChannelRevenueSummary:
      type: object
      title: SalesChannelRevenueSummary
      additionalProperties: false
      required:
        - sales_channel_id
        - gross_revenue
        - net_revenue
        - revenue_centres
      properties:
        sales_channel_id:
          type: string
          format: object-id
          nullable: true
          description: The ID of the sales channel. `null` for orders without a sales channel.
          example: 69c128bf5a210879a60ac186
        gross_revenue:
          type: integer
          description: Gross revenue attributed to this sales channel, in minor units.
          example: 250000
        net_revenue:
          type: integer
          description: Net revenue attributed to this sales channel, in minor units.
          example: 208000
        revenue_centres:
          type: array
          description: Per-revenue-centre breakdown of the totals above.
          items:
            $ref: '#/components/schemas/SalesChannelRevenueCentreSummary'
    RevenueBySalesChannelMeta:
      type: object
      title: RevenueBySalesChannelMeta
      additionalProperties: false
      required:
        - sales_channels
        - revenue_centres
      properties:
        sales_channels:
          type: array
          description: Lookup of the sales channels included in `data`, in display order.
          items:
            $ref: '#/components/schemas/SalesChannelSummary'
        revenue_centres:
          type: array
          description: Lookup of the revenue centres referenced in `data`, in display order.
          items:
            $ref: '#/components/schemas/RevenueCentreSummary'
    RevenueBySalesChannelResponse:
      type: object
      title: RevenueBySalesChannelResponse
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          type: array
          description: One entry per sales channel that contributed revenue in the filter range.
          items:
            $ref: '#/components/schemas/SalesChannelRevenueSummary'
        meta:
          $ref: '#/components/schemas/RevenueBySalesChannelMeta'
    RevenueProjectionDateStats:
      type: object
      title: RevenueProjectionDateStats
      additionalProperties: false
      required:
        - date
        - num_items
        - gross_revenue
        - net_revenue
      properties:
        date:
          type: string
          format: date
          example: '2026-06-15'
        num_items:
          type: integer
          example: 4
        gross_revenue:
          type: integer
          example: 60000
        net_revenue:
          type: integer
          example: 50000
    RevenueProjectionStats:
      type: object
      title: RevenueProjectionStats
      additionalProperties: false
      required:
        - num_items
        - gross_revenue
        - net_revenue
      properties:
        num_items:
          type: integer
        gross_revenue:
          type: integer
        net_revenue:
          type: integer
    RevenueProjectionOfferingWithPackages:
      type: object
      title: RevenueProjectionOfferingWithPackages
      additionalProperties: false
      required:
        - offering_id
        - offering_name
        - offering_type
        - revenue_centre
        - revenue_centre_name
        - category
        - by_date
        - totals
      properties:
        offering_id:
          type: string
          format: object-id
        offering_name:
          type: string
        offering_type:
          type: string
        package_type_id:
          type: string
          format: object-id
          nullable: true
        revenue_centre:
          type: string
          nullable: true
        revenue_centre_name:
          type: string
          nullable: true
        category:
          type: string
          nullable: true
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/RevenueProjectionDateStats'
        totals:
          $ref: '#/components/schemas/RevenueProjectionStats'
    RevenueProjectionOffering:
      type: object
      title: RevenueProjectionOffering
      additionalProperties: false
      required:
        - offering_id
        - offering_name
        - offering_type
        - by_date
        - totals
      properties:
        offering_id:
          type: string
          format: object-id
          example: 5e932c0901d210625e3a8766
        offering_name:
          type: string
          example: 60 Minute Massage
        offering_type:
          type: string
          example: appointment
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/RevenueProjectionDateStats'
        totals:
          $ref: '#/components/schemas/RevenueProjectionStats'
    RevenueProjectionRevenueCentre:
      type: object
      title: RevenueProjectionRevenueCentre
      additionalProperties: false
      required:
        - revenue_centre
        - revenue_centre_name
        - num_items
        - gross_revenue
        - net_revenue
        - by_date
      properties:
        revenue_centre:
          type: string
          nullable: true
        revenue_centre_name:
          type: string
          nullable: true
        num_items:
          type: integer
        gross_revenue:
          type: integer
        net_revenue:
          type: integer
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/RevenueProjectionDateStats'
    RevenueProjectionData:
      type: object
      title: RevenueProjectionData
      additionalProperties: false
      required:
        - with_package_groups
        - without_package_groups
        - by_revenue_centre
      properties:
        with_package_groups:
          type: array
          description: One entry per offering, with package sales rolled up into their parent package group.
          items:
            $ref: '#/components/schemas/RevenueProjectionOfferingWithPackages'
        without_package_groups:
          type: array
          description: One entry per offering, with package sales reported against their child offering instead of the parent.
          items:
            $ref: '#/components/schemas/RevenueProjectionOffering'
        by_revenue_centre:
          type: array
          description: One entry per revenue centre, with a per-day breakdown.
          items:
            $ref: '#/components/schemas/RevenueProjectionRevenueCentre'
    RevenueProjectionTotalsBreakdown:
      type: object
      title: RevenueProjectionTotalsBreakdown
      additionalProperties: false
      required:
        - num_items
        - gross_revenue
        - net_revenue
        - by_date
      properties:
        num_items:
          type: integer
        gross_revenue:
          type: integer
        net_revenue:
          type: integer
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/RevenueProjectionDateStats'
    RevenueProjectionTotals:
      type: object
      title: RevenueProjectionTotals
      additionalProperties: false
      required:
        - with_package_groups
        - without_package_groups
        - by_date
        - num_items
        - gross_revenue
        - net_revenue
      properties:
        with_package_groups:
          $ref: '#/components/schemas/RevenueProjectionTotalsBreakdown'
        without_package_groups:
          $ref: '#/components/schemas/RevenueProjectionTotalsBreakdown'
        by_date:
          type: array
          items:
            $ref: '#/components/schemas/RevenueProjectionDateStats'
        num_items:
          type: integer
        gross_revenue:
          type: integer
        net_revenue:
          type: integer
    RevenueProjectionResponse:
      type: object
      title: RevenueProjectionResponse
      additionalProperties: false
      description: |
        A projection of expected revenue across the next 31 days, broken down both with and
        without package-group rollups, plus a by-revenue-centre split.
      required:
        - data
        - totals
      properties:
        data:
          $ref: '#/components/schemas/RevenueProjectionData'
        totals:
          $ref: '#/components/schemas/RevenueProjectionTotals'
    RoomOccupancyRoom:
      type: object
      title: RoomOccupancyRoom
      additionalProperties: false
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: object-id
          example: 60a8c0901d210625e3a87667
        name:
          type: string
          example: Treatment Room 1
    RoomOccupancyRow:
      type: object
      title: RoomOccupancyRow
      additionalProperties: false
      required:
        - room
        - bookable_mins
        - appointment_mins
        - session_mins
        - blocked_mins
      properties:
        room:
          $ref: '#/components/schemas/RoomOccupancyRoom'
        bookable_mins:
          type: integer
          example: 2400
        appointment_mins:
          type: integer
          example: 1500
        session_mins:
          type: integer
          example: 200
        blocked_mins:
          type: integer
          example: 60
    RoomOccupancyTotals:
      type: object
      title: RoomOccupancyTotals
      additionalProperties: false
      required:
        - bookable_mins
        - appointment_mins
        - session_mins
        - blocked_mins
      properties:
        bookable_mins:
          type: integer
        appointment_mins:
          type: integer
        session_mins:
          type: integer
        blocked_mins:
          type: integer
    RoomOccupancyResponse:
      type: object
      title: RoomOccupancyResponse
      additionalProperties: false
      description: |
        For each room at the site, the number of bookable / appointment / session / blocked
        minutes across the requested date range.
      required:
        - data
        - totals
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/RoomOccupancyRow'
        totals:
          $ref: '#/components/schemas/RoomOccupancyTotals'
    RunSheetEvent:
      type: object
      title: RunSheetEvent
      additionalProperties: false
      required:
        - id
        - type
        - start_time
        - end_time
        - event_name
        - practitioner_name
        - room_name
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the appointment or session.
        type:
          type: string
          description: Whether this event is an appointment or session.
          enum:
            - appointment
            - session
        start_time:
          type: string
          format: date-time
          description: The start time of the event in the site's timezone.
        end_time:
          type: string
          format: date-time
          description: The end time of the event in the site's timezone.
        event_name:
          type: string
          description: The name of the appointment type or session type.
          example: 60 Minute Massage
        practitioner_name:
          type: string
          nullable: true
          description: A comma-separated list of practitioners assigned to the event.
          example: Sarah Smith
        room_name:
          type: string
          nullable: true
          description: The name of the room the event is in.
          example: Treatment Room 1
        customer_name:
          type: string
          nullable: true
          description: The name of the customer for the booking (appointments only).
        session_capacity:
          type: integer
          nullable: true
          description: The capacity of the session (sessions only).
        session_booked_customers:
          type: integer
          nullable: true
          description: The number of customers booked into the session (sessions only).
    RunSheetResponse:
      type: object
      title: RunSheetResponse
      additionalProperties: false
      required:
        - data
      properties:
        data:
          type: array
          description: The events (appointments and sessions) scheduled for the day, sorted by start time.
          items:
            $ref: '#/components/schemas/RunSheetEvent'
    TopCustomer:
      type: object
      title: TopCustomer
      additionalProperties: false
      required:
        - id
        - full_name
        - num_orders
        - total_value_gross
        - average_value_gross
        - total_value_net
        - average_value_net
      properties:
        id:
          type: string
          format: object-id
          description: The customer's ID.
          example: 60a8c0901d210625e3a87667
        full_name:
          type: string
          description: The most common name the customer has used on their orders.
          example: Jane Doe
        num_orders:
          type: integer
          description: The number of submitted or settled orders by this customer in the filter range.
          example: 8
        total_value_gross:
          type: integer
          description: The sum of gross order totals for this customer, in minor units.
          example: 240000
        average_value_gross:
          type: integer
          description: The average gross order total for this customer, in minor units.
          example: 30000
        total_value_net:
          type: integer
          description: The sum of net order totals for this customer, in minor units.
          example: 200000
        average_value_net:
          type: integer
          description: The average net order total for this customer, in minor units.
          example: 25000
    TopCustomersResponse:
      type: object
      title: TopCustomersResponse
      additionalProperties: false
      required:
        - data
      properties:
        data:
          type: array
          description: The top 100 customers by net total within the filter range, sorted by net total descending.
          items:
            $ref: '#/components/schemas/TopCustomer'
    TopOffering:
      type: object
      title: TopOffering
      additionalProperties: false
      required:
        - offering_id
        - offering_type
        - offering_name
        - num_standalone_items
        - num_package_items
        - gross_revenue
        - net_revenue
      properties:
        offering_id:
          type: string
          format: object-id
        offering_type:
          type: string
          example: appointment
        offering_name:
          type: string
          example: 60 Minute Massage
        num_standalone_items:
          type: integer
          description: Number of times the offering was sold as a standalone item.
        num_package_items:
          type: integer
          description: Number of times the offering was sold as part of a package.
        gross_revenue:
          type: integer
          description: Combined gross revenue for the standalone sales, in minor units.
        net_revenue:
          type: integer
          description: Combined net revenue for the standalone sales, in minor units.
    TopOfferingTypeTotal:
      type: object
      title: TopOfferingTypeTotal
      additionalProperties: false
      required:
        - offering_type
        - num_standalone_items
        - num_package_items
        - gross_revenue
        - net_revenue
      properties:
        offering_type:
          type: string
          example: appointment
        num_standalone_items:
          type: integer
        num_package_items:
          type: integer
        gross_revenue:
          type: integer
        net_revenue:
          type: integer
    TopOfferingTotals:
      type: object
      title: TopOfferingTotals
      additionalProperties: false
      required:
        - by_offering_type
      properties:
        by_offering_type:
          type: array
          description: Each entry rolls up the offerings of a single type — appointment, session, package, etc.
          items:
            type: array
            title: TopOfferingTypeBucket
            items:
              $ref: '#/components/schemas/TopOfferingTypeTotal'
    TopOfferingsResponse:
      type: object
      title: TopOfferingsResponse
      additionalProperties: false
      required:
        - data
        - totals
      properties:
        data:
          type: array
          description: The top offerings by item count and revenue across the filter range.
          items:
            $ref: '#/components/schemas/TopOffering'
        totals:
          $ref: '#/components/schemas/TopOfferingTotals'
    TrybePaymentsBalanceTransfer:
      type: object
      title: TrybePaymentsBalanceTransfer
      additionalProperties: false
      required:
        - id
        - time
        - event
        - type
        - amount
        - balance
      properties:
        id:
          type: string
          description: The Adyen transfer ID.
        time:
          type: string
          format: date-time
        event:
          type: string
          description: The Adyen event name that produced this balance movement.
          example: AUTHORISATION
        type:
          type: string
          example: card_payment
        payment_id:
          type: string
          format: object-id
          nullable: true
        refund_id:
          type: string
          format: object-id
          nullable: true
        payable_id:
          type: string
          format: object-id
          nullable: true
        payable_type:
          type: string
          nullable: true
          description: The downcased class basename of the payable model (e.g. `basket`, `membership`).
        order_ref:
          type: string
          nullable: true
        amount:
          type: integer
          description: The transfer amount, in minor units. Positive for credits, negative for debits.
        balance:
          type: integer
          description: The running balance after this transfer, in minor units.
    TrybePaymentsBalanceResponse:
      type: array
      title: TrybePaymentsBalanceResponse
      description: |
        A paginated array of Trybe Payments (Adyen balance platform) transfers in the requested
        period. Each entry represents a single balance movement — a payment in, a refund out,
        or a payout. Money values are integers in minor units. The `meta` block accompanying
        the response carries the opening balance, closing balance, currency, and standard
        Laravel pagination fields.
      items:
        $ref: '#/components/schemas/TrybePaymentsBalanceTransfer'
    VoucherCodeListItem:
      type: object
      title: VoucherCodeListItem
      additionalProperties: true
      required:
        - id
        - code
        - status
        - amount_type
        - amount
        - balance
        - currency
        - voucher_type
      properties:
        id:
          type: string
          format: object-id
        code:
          type: string
          example: TRYBE-ABC123
        status:
          type: string
          example: issued
        valid_from_date:
          type: string
          format: date-time
          nullable: true
        valid_to_date:
          type: string
          format: date-time
          nullable: true
        amount_type:
          type: string
          description: How the voucher's face value should be interpreted (e.g. `currency` or `monetary`).
          example: monetary
        amount:
          type: integer
          description: The face value of the voucher in minor units.
          example: 5000
        balance:
          type: integer
          description: The remaining balance on the voucher in minor units.
          example: 5000
        currency:
          type: string
          example: gbp
        value:
          type: integer
          description: Alias of `amount` retained for backwards compatibility.
        partially_redeemable:
          type: boolean
        imported:
          type: boolean
          description: Whether the voucher was bulk-imported rather than purchased through Trybe.
        fulfillment_status:
          type: string
          nullable: true
        voucher_type:
          type: object
          title: VoucherCodeVoucherType
          additionalProperties: false
          required:
            - id
            - name
          properties:
            id:
              type: string
              format: object-id
            name:
              type: string
              example: £50 Spa Day Voucher
        recipient:
          type: object
          title: VoucherCodeRecipient
          additionalProperties: true
          description: Recipient information collected at purchase.
        delivery:
          type: object
          title: VoucherCodeDelivery
          additionalProperties: true
          description: Delivery method, option, and target date for the voucher.
        order:
          type: object
          title: VoucherCodeOrderSummary
          additionalProperties: true
          description: A short summary of the order this voucher was purchased on.
        redemptions:
          type: array
          description: When requested with `?include=redemptions`, an array of payments that have been settled against this code.
          items:
            type: object
            title: VoucherCodeRedemption
            additionalProperties: true
            required:
              - payment_id
            properties:
              payment_id:
                type: string
                format: object-id
              amount:
                type: integer
              refunded_amount:
                type: integer
              paid_at:
                type: string
                format: date-time
                nullable: true
              payable_id:
                type: string
                format: object-id
              order_ref:
                type: string
        created_at:
          type: string
          format: date-time
        issued_at:
          type: string
          format: date-time
          nullable: true
    VoucherCodesResponse:
      type: object
      title: VoucherCodesResponse
      additionalProperties: false
      required:
        - data
        - meta
        - links
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/VoucherCodeListItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
    VoucherLedgerEntry:
      type: object
      title: VoucherLedgerEntry
      additionalProperties: true
      required:
        - date
        - type
        - revenue_centre
        - description
        - gross_amount
        - net_amount
        - tax_amount
      properties:
        date:
          type: string
          format: date-time
        type:
          type: string
          enum:
            - revenue
            - payment
            - refund
        revenue_centre:
          type: string
          example: voucher
        description:
          type: string
          example: Trybe Voucher Sales
        gross_amount:
          type: integer
        net_amount:
          type: integer
        tax_amount:
          type: integer
        meta:
          type: object
          title: VoucherLedgerEntryMeta
          additionalProperties: true
          description: |
            Contextual references for the ledger entry — e.g. `order_ref`, `basket_id`,
            `payment_id`, `voucher_code_id`, or `refund_id` depending on the entry type.
    VoucherLedgerDetailedResponse:
      type: array
      title: VoucherLedgerDetailedResponse
      description: |
        A chronologically-sorted ledger of voucher-related revenue, redemptions, and refunds in
        the requested period. Money fields are integers in minor units. The `meta` block
        accompanying the response (see `with` block) carries the opening and closing balances.
      items:
        $ref: '#/components/schemas/VoucherLedgerEntry'
    VoucherLedgerRevenueLine:
      type: object
      title: VoucherLedgerRevenueLine
      additionalProperties: false
      required:
        - revenue_centre
        - description
        - gross_amount
        - net_amount
        - tax_amount
        - count
      properties:
        revenue_centre:
          type: string
          example: voucher
        description:
          type: string
          example: Trybe Voucher Sales
        gross_amount:
          type: integer
        net_amount:
          type: integer
        tax_amount:
          type: integer
        count:
          type: integer
    VoucherLedgerPaymentLine:
      type: object
      title: VoucherLedgerPaymentLine
      additionalProperties: false
      required:
        - revenue_centre
        - description
        - amount
        - count
      properties:
        revenue_centre:
          type: string
          example: voucher_redemption
        description:
          type: string
          example: Trybe Voucher Redemptions
        amount:
          type: integer
          description: A negative number representing the value of vouchers redeemed in the period.
        count:
          type: integer
    VoucherLedgerMeta:
      type: object
      title: VoucherLedgerMeta
      additionalProperties: false
      required:
        - currency
        - opening_balance
        - closing_balance
      properties:
        currency:
          type: string
          example: gbp
        opening_balance:
          type: integer
          description: The outstanding voucher liability balance at the start of the period, in minor units.
        closing_balance:
          type: integer
          description: The outstanding voucher liability balance at the end of the period, in minor units.
    VoucherLedgerSummaryResponseDate:
      type: object
      title: VoucherLedgerSummaryResponseDate
      additionalProperties: false
      description: |
        Summary of voucher revenue and redemptions for the given date range. Money fields are
        integers in minor units. Use this report to reconcile the deferred-revenue balance held
        against Trybe voucher sales.
      required:
        - revenues
        - payments
        - meta
      properties:
        revenues:
          $ref: '#/components/schemas/VoucherLedgerRevenueLine'
        payments:
          $ref: '#/components/schemas/VoucherLedgerPaymentLine'
        meta:
          $ref: '#/components/schemas/VoucherLedgerMeta'
    offeringType:
      type: string
      description: |
        The kind of offering a rule applies to. Limited to offerings booked against a
        service date, which is what demand is measured over.
      enum:
        - appointment
        - area_booking
        - session
        - package
    yieldAdjustmentType:
      type: string
      description: |
        Whether the adjustment is a fixed amount in minor units, or a percentage of
        the price it applies to.
      enum:
        - amount
        - percentage
    YieldRuleAdjustment:
      title: YieldRuleAdjustment
      description: |
        The change a rule makes to the price it applies to. Signed, so a rule can
        discount to shift demand as well as add a premium at peak.
      type: object
      additionalProperties: false
      properties:
        type:
          $ref: '#/components/schemas/yieldAdjustmentType'
        value:
          type: integer
          description: |
            Integer minor units when `type` is `amount`, matching `standard_price`;
            whole percent when `type` is `percentage`.
          example: 15
      required:
        - type
        - value
    yieldReportingTier:
      type: string
      description: |
        Groups yielded sales in reporting. Descriptive only — it never affects the
        adjustment a rule makes. Sales made when no rule applied report as an
        implicit standard tier, which is why it is absent here. The
        [yielded sales report](/endpoints/Reports#listYieldedSales) lists and
        totals sales by this tier.
      enum:
        - low
        - high
        - peak
    YieldedSale:
      title: YieldedSale
      description: |
        A sale where a yield rule moved the price, as it was at the time of
        sale. The rule, tier, fill rate, and prices are provenance stored when
        the price was resolved — they never change when the rule or offering is
        later edited, renamed, or deleted.
      type: object
      additionalProperties: false
      required:
        - id
        - basket_id
        - order_ref
        - sold_at
        - status
        - offering_id
        - offering_type
        - offering_name
        - offering_exists
        - yield_rule_id
        - yield_rule_exists
        - adjustment
        - tier
        - fill_rate_percent
        - currency
        - baseline_price
        - price_paid
        - delta_amount
        - delta_percent
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the basket item the yielded price was sold on.
          example: 60a8c0901d210625e3a87667
        basket_id:
          type: string
          format: object-id
          example: 60a8c0901d210625e3a87668
        order_ref:
          type: string
          example: TRY03
        sold_at:
          type: string
          format: date-time
          description: |
            When the order was submitted, expressed in the site's local
            timezone.
        status:
          type: string
          description: |
            `completed` sales count towards the report totals. `refunded` and
            `cancelled` sales stay listed for reconciliation but are excluded
            from the revenue and net-uplift totals.
          enum:
            - completed
            - refunded
            - cancelled
          example: completed
        offering_id:
          type: string
          description: The offering the sale was for.
        offering_type:
          $ref: '#/components/schemas/offeringType'
        offering_name:
          type: string
          description: |
            The offering's name at the time of sale. Kept even when the
            offering has since been renamed or deleted — check
            `offering_exists` before treating it as current.
          example: 60 Minute Massage
        offering_exists:
          type: boolean
          description: Whether the offering still exists (and is not deleted).
          example: true
        yield_rule_id:
          type: string
          format: uuid
          description: |
            The yield rule that moved the price, as recorded at the time of
            sale. The rule may have been edited or deleted since — check
            `yield_rule_exists` before linking to it.
        yield_rule_exists:
          type: boolean
          description: Whether the yield rule still exists (and is not deleted).
          example: true
        adjustment:
          $ref: '#/components/schemas/YieldRuleAdjustment'
        tier:
          $ref: '#/components/schemas/yieldReportingTier'
        fill_rate_percent:
          type: integer
          nullable: true
          description: |
            The demand measurement (practitioner utilisation or room occupancy,
            whichever satisfied the rule's trigger) at the time of sale, as a
            whole-number percentage. `null` when no measurement was recorded.
          example: 85
        currency:
          type: string
          description: |
            The ISO-4217 currency code the row's monetary amounts are
            denominated in, in integer minor units.
          example: GBP
        baseline_price:
          type: integer
          nullable: true
          description: |
            What the item would have cost without the yield adjustment, in
            integer minor units. `null` when the offering had no standard price
            at the time of sale, in which case the row is excluded from the
            net-uplift totals.
          example: 5000
        price_paid:
          type: integer
          description: What the item actually sold for, in integer minor units.
          example: 5750
        delta_amount:
          type: integer
          nullable: true
          description: |
            `price_paid` minus `baseline_price`, in integer minor units.
            Negative when a low-tier rule discounted the price. `null` when
            `baseline_price` is `null`.
          example: 750
        delta_percent:
          type: integer
          nullable: true
          description: |
            The delta as a whole-number percentage of `baseline_price`.
            Negative when a low-tier rule discounted the price. `null` when
            `baseline_price` is `null`.
          example: 15
    YieldedSalesTierTotals:
      title: YieldedSalesTierTotals
      type: object
      additionalProperties: false
      required:
        - tier
        - count
        - revenue
        - net_uplift
      properties:
        tier:
          $ref: '#/components/schemas/yieldReportingTier'
        count:
          type: integer
          description: |
            The number of yielded sales in this tier, including refunded and
            cancelled sales.
          example: 120
        revenue:
          type: integer
          description: |
            Total `price_paid` across completed sales in this tier, in integer
            minor units. Refunded and cancelled sales are excluded.
          example: 690000
        net_uplift:
          type: integer
          description: |
            Total `delta_amount` across completed sales in this tier, in
            integer minor units. Typically negative for the `low` tier, since
            its rules discount the price. Rows with no `baseline_price` are
            excluded.
          example: 90000
    YieldedSalesCurrencyTotals:
      title: YieldedSalesCurrencyTotals
      type: object
      additionalProperties: false
      required:
        - currency
        - revenue
        - net_uplift
        - tiers
      properties:
        currency:
          type: string
          description: |
            The ISO-4217 currency code the totals in this entry are denominated
            in, in integer minor units.
          example: GBP
        revenue:
          type: integer
          description: |
            Total `price_paid` across completed yielded sales in this currency.
            Refunded and cancelled sales are excluded.
          example: 1966500
        net_uplift:
          type: integer
          description: |
            Total `delta_amount` across completed yielded sales in this
            currency — what yielding earned versus the baseline prices. Low-tier
            discounts net against high- and peak-tier increases, so this can be
            negative. Rows with no `baseline_price` are excluded.
          example: 256500
        tiers:
          type: array
          description: The same totals broken down by reporting tier.
          items:
            $ref: '#/components/schemas/YieldedSalesTierTotals'
    YieldedSalesTotals:
      title: YieldedSalesTotals
      description: |
        Aggregates over every row matching the active filters, not just the
        current page. Monetary totals are grouped per currency and never summed
        across currencies; `refunded` and `cancelled` sales and rows with no
        `baseline_price` are excluded as described on each field.
      type: object
      additionalProperties: false
      required:
        - count
        - currencies
      properties:
        count:
          type: integer
          description: |
            The number of yielded sales matching the active filters, including
            refunded and cancelled sales.
          example: 342
        currencies:
          type: array
          description: |
            One entry per currency appearing in the filtered results. A single
            site reports in one currency, so this usually has one entry;
            historical currency changes produce one entry per currency rather
            than a sum across them.
          items:
            $ref: '#/components/schemas/YieldedSalesCurrencyTotals'
    YieldedSalesReportResponse:
      title: YieldedSalesReportResponse
      type: object
      additionalProperties: false
      required:
        - data
        - meta
        - links
        - totals
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/YieldedSale'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'
        totals:
          $ref: '#/components/schemas/YieldedSalesTotals'
    BlockedTimePreset:
      title: BlockedTimePreset
      description: |
        A `BlockedTimePreset` captures the reusable defaults for a
        common kind of blocked time — e.g. "Lunch break" (30 min,
        `break`), "Deep clean" (15 min, `cleaning`). Operators pick a
        preset in the calendar UI to create a `BlockedTime` with the
        preset's `duration`, `type`, `label`, `notes`, and `color`
        pre-filled.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the preset.
          example: 65f1234567890abcdef12345
        name:
          type: string
          description: Display name shown in the preset picker. Plain text only.
          example: Lunch break
        duration:
          type: integer
          description: |
            Default duration in minutes for a `BlockedTime` created
            from this preset. Must be at most 1200 (20 hours).
          minimum: 1
          maximum: 1200
          example: 30
        type:
          type: string
          description: Default block type. Drives the calendar icon.
          enum:
            - cleaning
            - break
            - meeting
            - other
          example: break
        label:
          type: string
          nullable: true
          description: Default short label on the calendar tile. Plain text only.
          example: Lunch
        notes:
          type: string
          nullable: true
          description: Default free-form note (plain text).
        color:
          type: string
          nullable: true
          description: |
            Default hex colour (`#rrggbb`, lower-case) to override the
            type's default colour.
          example: '#ff8800'
        site_id:
          type: string
          format: uuid
          description: ID of the site this preset belongs to.
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation that owns this preset.
      required:
        - id
        - name
        - site_id
        - organisation_id
    BlockedTime:
      title: BlockedTime
      description: |
        A `BlockedTime` carves a window out of one or more resource
        calendars (practitioners, rooms, or bookable areas) so they
        cannot be booked during that window. Use blocked times for
        breaks, cleaning, internal meetings, or any other reason an
        otherwise-available resource should be hidden from availability.

        At least one of `practitioner_ids`, `room_ids`, or `area_ids`
        must be non-empty — a blocked time always targets at least one
        resource.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the blocked time.
          example: 65f1234567890abcdef12345
        start_time:
          type: string
          format: date-time
          description: |
            Start of the blocked window. Stored as a date-time in the
            site's timezone.
          example: '2026-06-01T09:00:00+01:00'
        end_time:
          type: string
          format: date-time
          description: |
            End of the blocked window. Must be strictly after
            `start_time`.
          example: '2026-06-01T09:30:00+01:00'
        type:
          type: string
          description: |
            The kind of block. Drives the icon shown on the operator
            calendar and acts as an audit aid.
          enum:
            - cleaning
            - break
            - meeting
            - other
          example: cleaning
        label:
          type: string
          nullable: true
          description: |
            Optional short label shown on the calendar tile. Plain text
            only.
          example: Deep clean
        notes:
          type: string
          nullable: true
          description: |
            Optional longer note (free-form, plain text). Visible to
            operators on the calendar tile.
          example: Used the extra steamer
        color:
          type: string
          nullable: true
          description: |
            Optional hex colour (`#RRGGBB`, lower-case) to override the
            default colour for this `type` on the calendar.
          example: '#ff8800'
        practitioner_ids:
          type: array
          description: |
            Practitioner calendars covered by this blocked time. May be
            empty if the block targets rooms or areas only.
          items:
            type: string
            format: object-id
        room_ids:
          type: array
          description: |
            Room calendars covered by this blocked time. May be empty.
          items:
            type: string
            format: object-id
        area_ids:
          type: array
          description: |
            Bookable-area calendars covered by this blocked time. May be
            empty.
          items:
            type: string
            format: object-id
        site_id:
          type: string
          format: uuid
          description: ID of the site this blocked time belongs to.
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation that owns this blocked time.
      required:
        - id
        - start_time
        - end_time
        - type
        - practitioner_ids
        - room_ids
        - area_ids
        - site_id
        - organisation_id
    BlockedTimeRecurrence:
      title: BlockedTimeRecurrence
      description: |
        Optional recurrence configuration sent with a `BlockedTime`
        create request. When `weekdays` is non-empty, the server fans
        out copies of the blocked time across the matching weekdays in
        `date_from`..`date_to`.

        The configured range cannot exceed 366 days.
      type: object
      additionalProperties: false
      properties:
        weekdays:
          type: array
          description: |
            Weekdays the blocked time should repeat on. Empty/omitted
            disables recurrence.
          items:
            type: string
            enum:
              - monday
              - tuesday
              - wednesday
              - thursday
              - friday
              - saturday
              - sunday
        date_from:
          type: string
          format: date
          nullable: true
          description: |
            First day of the recurrence range (inclusive), in the site's
            timezone. Defaults to today when omitted. Must be today or
            later.
        date_to:
          type: string
          format: date
          nullable: true
          description: |
            Last day of the recurrence range (inclusive). Required when
            `weekdays` is set.
    AppointmentSlotWarning:
      title: AppointmentSlotWarning
      description: |
        A warning relating to an appointment availability slot.
        Mirrors order-item warnings but can also scope the warning to a
        specific practitioner.
      type: object
      additionalProperties: false
      properties:
        code:
          type: string
          description: A machine-readable code identifying the type of warning.
          example: no_practitioner_assigned
        message:
          type: string
          description: A human-readable message describing the warning.
        practitioner_id:
          type: string
          description: |
            Practitioner this warning applies to, when relevant.
          nullable: true
      required:
        - code
        - message
    AppointmentAvailabilitySlot:
      title: AppointmentAvailabilitySlot
      description: |
        A single bookable slot returned by the appointment-availability
        endpoint. Each slot represents a specific start time at which
        the requested `AppointmentType` can be booked, alongside any
        resource hints needed to confirm the booking.
      type: object
      additionalProperties: false
      properties:
        start_time:
          type: string
          format: date-time
          description: The slot's start time, in the site's timezone.
        end_time:
          type: string
          format: date-time
          description: |
            The slot's end time, including any post-appointment buffer.
        duration:
          type: integer
          description: Appointment duration in minutes (excluding the buffer).
        end_buffer:
          type: integer
          description: Post-appointment buffer (cleaning time) in minutes.
        practitioner_ids:
          type: array
          description: |
            Practitioners eligible to deliver the appointment at this
            slot.
          items:
            type: string
        room_ids:
          type: array
          description: |
            Rooms eligible for this slot. Only returned for internal
            users.
          items:
            type: string
        equipment_ids:
          type: array
          description: |
            Equipment available for this slot. Only returned for
            internal users.
          items:
            type: string
        total_quantity:
          type: integer
          description: |
            Total slots that could be offered at this time if all
            resources were available.
        quantity_available:
          type: integer
          description: |
            Slots currently free at this start time after accounting for
            existing bookings.
        is_valid:
          type: boolean
          description: |
            Whether the slot passed every availability rule. `false`
            slots are returned for context but cannot be booked.
        currency:
          type: string
          description: Currency code of `price` (ISO 4217, lower-case).
          example: gbp
        price:
          type: integer
          description: Slot price in the smallest currency unit (e.g. pence).
        nonoptimal_practitioner_allocation:
          type: boolean
          description: |
            `true` when booking this slot would create a low-value gap
            in every otherwise-available practitioner's calendar.
        nonoptimal_practitioner_ids:
          type: array
          description: |
            Practitioners for whom this slot would be a non-optimal
            allocation.
          items:
            type: string
        bookable_from:
          type: string
          format: date-time
          nullable: true
          description: |
            Earliest date-time the slot may be booked. Useful for
            rendering countdowns on UIs that expose future bookable
            windows.
        bookable_to:
          type: string
          format: date-time
          nullable: true
          description: Date-time after which the slot may not be booked.
        no_availability_reason:
          type: string
          nullable: true
          description: |
            Machine-readable reason for `is_valid=false`. One of
            `time_passed`, `date_passed`, `no_longer_bookable`,
            `not_yet_bookable`, `partner_slot_not_available`,
            `partner_offering_not_allowed`, `start_time_not_allowed`,
            `no_equipment_available`, `no_rooms_available`,
            `no_practitioners_available`, `invalid_offering_settings`,
            `not_offered_on_date`, or `null` when the slot is valid.
        no_availability_message:
          type: string
          nullable: true
          description: |
            User-friendly reason for `is_valid=false`, suitable for UI
            display.
        warnings:
          type: array
          nullable: true
          description: |
            Non-blocking warnings relevant to booking this slot.
          items:
            $ref: '#/components/schemas/AppointmentSlotWarning'
      required:
        - start_time
        - end_time
        - duration
        - end_buffer
        - practitioner_ids
        - total_quantity
        - quantity_available
        - is_valid
        - currency
        - price
    AppointmentSlotsMeta:
      title: AppointmentSlotsMeta
      description: |
        Metadata returned alongside the appointment slot list. Useful
        for rendering practitioner pickers, no-availability messaging,
        and the appointment type's practitioner-selection mode.
      type: object
      additionalProperties: true
      properties:
        practitioners:
          type: array
          description: Summary records for every practitioner referenced by any slot.
          items:
            type: object
            additionalProperties: true
        practitioner_selection:
          type: string
          nullable: true
          description: |
            How the shop should present the practitioner choice for
            this appointment type — `any`, `customer_choice`, etc.
        no_availability_reason:
          type: string
          nullable: true
          description: |
            Reason there are no slots at all. Returned when the slot
            list is empty.
    AreaBookingAvailabilitySlot:
      title: AreaBookingAvailabilitySlot
      description: |
        A single bookable area-booking slot. Each slot represents a
        specific start time at which the requested `AreaBookingType`
        can be booked.
      type: object
      additionalProperties: false
      properties:
        start_time:
          type: string
          format: date-time
        end_time:
          type: string
          format: date-time
        duration:
          type: integer
          description: Duration in minutes.
        area_ids:
          type: array
          description: |
            Bookable areas that can host this slot.
          items:
            type: string
        total_quantity:
          type: integer
        quantity_available:
          type: integer
        is_valid:
          type: boolean
        currency:
          type: string
          example: gbp
        price:
          type: integer
          description: Slot price in the smallest currency unit.
        no_availability_reason:
          type: string
          nullable: true
        no_availability_message:
          type: string
          nullable: true
      required:
        - start_time
        - end_time
        - duration
        - total_quantity
        - quantity_available
        - is_valid
        - currency
        - price
    MultiAppointmentSlotItemInput:
      title: MultiAppointmentSlotItemInput
      description: |
        One item in the multi-appointment request payload. Identifies
        which appointment type to slot in plus any per-item overrides.
      type: object
      additionalProperties: true
      properties:
        appointment_type_id:
          type: string
          description: ID of the `AppointmentType` to schedule.
        duration:
          type: integer
          description: Optional duration override for this item.
        quantity:
          type: integer
          description: Optional guest quantity for this item.
      required:
        - appointment_type_id
    MultiAppointmentSlotEntry:
      title: MultiAppointmentSlotEntry
      description: |
        A single appointment-slot entry within a
        `MultiAppointmentSlotGroup`. Identifies the appointment type,
        its time window, and the assigned practitioner.
      type: object
      additionalProperties: false
      required:
        - appointment_type_id
        - start_time
        - end_time
        - duration
        - end_buffer
        - practitioner_id
        - price
      properties:
        appointment_type_id:
          type: string
          description: ID of the appointment type this slot fills.
        start_time:
          type: string
          format: date-time
          description: Slot start time, in the site's timezone.
        end_time:
          type: string
          format: date-time
          description: Slot end time including any post-appointment buffer.
        duration:
          type: integer
          description: Duration in minutes.
        end_buffer:
          type: integer
          description: Post-appointment buffer (cleaning time) included in `end_time`.
        practitioner_id:
          type: string
          description: Practitioner assigned to this slot.
        price:
          type: integer
          description: |
            Per-slot price in the smallest currency unit, with any
            applicable basket discounts already applied.
    MultiAppointmentSlotGroup:
      title: MultiAppointmentSlotGroup
      description: |
        A grouping of multiple appointment-type slots that can be
        booked together at a common start time. Used by the booking UI
        when a customer adds several appointments to their basket and
        needs them to chain back-to-back.
      type: object
      additionalProperties: false
      properties:
        start_time:
          type: string
          format: date-time
        nonoptimal_practitioner_allocation:
          type: boolean
          description: |
            Whether the chosen combination leaves a low-value gap in a
            practitioner's calendar.
        total_cost:
          type: integer
          description: |
            Total cost of the combined appointments in the smallest
            currency unit.
        appointments:
          type: array
          description: |
            The individual appointment slots — one per appointment type
            in the request.
          items:
            $ref: '#/components/schemas/MultiAppointmentSlotEntry'
      required:
        - start_time
        - total_cost
        - appointments
    OfferingDateAvailability:
      title: OfferingDateAvailability
      description: |
        Per-day availability for an `Offering`. Returned by the
        `offering-dates` endpoint to power calendar UIs that highlight
        bookable days.
      type: object
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: The day this entry refers to (in the offering's timezone).
        has_availability:
          type: boolean
          description: Whether at least one slot is bookable on this day.
        practitioner_ids:
          type: array
          description: |
            Practitioners with availability on this day. Only returned
            for offerings that surface a practitioner picker.
          items:
            type: string
        can_enquire:
          type: boolean
          nullable: true
          description: |
            For days with no live availability, whether the appointment
            type supports an enquiry instead. `null` for offerings that
            don't support enquiries.
        bookable_from:
          type: string
          format: date-time
          nullable: true
          description: |
            Earliest date-time on this day at which the offering may be
            booked.
        bookable_to:
          type: string
          format: date-time
          nullable: true
          description: |
            Latest date-time on this day at which the offering may be
            booked.
        price_from:
          type: integer
          nullable: true
          description: |
            Cheapest slot price on this day in the smallest currency
            unit. `null` when no slots are bookable.
      required:
        - date
        - has_availability
    PackageChoiceSlot:
      title: PackageChoiceSlot
      description: |
        A bookable slot for one of the items in a `Package` choice.
        The shape mirrors `AppointmentAvailabilitySlot` plus a
        `package_item_id` tying the slot to a specific choice.
      type: object
      additionalProperties: true
      properties:
        package_item_id:
          type: string
          description: ID of the package item this slot belongs to.
        start_time:
          type: string
          format: date-time
        end_time:
          type: string
          format: date-time
        duration:
          type: integer
        practitioner_ids:
          type: array
          items:
            type: string
        quantity_available:
          type: integer
        is_valid:
          type: boolean
      required:
        - package_item_id
        - start_time
        - end_time
        - duration
    ProductStockAvailability:
      title: ProductStockAvailability
      description: |
        Stock availability for a single `Product` at a single site,
        plus any partner-specific allotment overrides.
      type: object
      additionalProperties: false
      properties:
        product_id:
          type: string
          description: The product ID.
        site_id:
          type: string
          description: The site the stock is sold from.
        quantity_available:
          type: integer
          description: |
            Units currently available for sale. Stock-tracking products
            return their on-hand count; non-tracking products return a
            large sentinel value (effectively unlimited).
        can_purchase:
          type: boolean
          description: |
            `true` when at least one unit can be added to a basket
            right now.
        no_availability_reason:
          type: string
          nullable: true
          description: Machine-readable reason for `can_purchase=false`.
      required:
        - product_id
        - site_id
        - quantity_available
        - can_purchase
    SessionAvailabilityOccurrence:
      title: SessionAvailabilityOccurrence
      description: |
        A single session occurrence — a scheduled instance of a
        `SessionType` — with current availability and pricing.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: Occurrence ID.
        start_time:
          type: string
          format: date-time
        end_time:
          type: string
          format: date-time
        duration:
          type: integer
          description: Occurrence duration in minutes.
        capacity:
          type: integer
          description: Total capacity for this occurrence.
        quantity_available:
          type: integer
          description: Remaining capacity after existing bookings.
        is_bookable:
          type: boolean
          description: Whether the occurrence is currently bookable.
        currency:
          type: string
          example: gbp
        price:
          type: integer
          description: Per-guest price in the smallest currency unit.
        no_availability_reason:
          type: string
          nullable: true
      required:
        - start_time
        - end_time
        - duration
        - capacity
        - quantity_available
        - is_bookable
        - currency
        - price
    OrderItineraryBooking:
      title: OrderItineraryBooking
      type: object
      additionalProperties: false
      description: A single booking line on an order itinerary.
      properties:
        name:
          type: string
          description: The offering's display name.
          example: Aromatherapy Massage
        start_time:
          type: string
          format: date-time
          description: When the booking starts.
          example: '2026-04-12T14:00:00+01:00'
        end_time:
          type: string
          format: date-time
          description: When the booking ends.
          example: '2026-04-12T15:00:00+01:00'
      required:
        - name
        - start_time
        - end_time
    OrderItineraryDay:
      title: OrderItineraryDay
      type: object
      additionalProperties: false
      description: All bookings for the guest bucket on a single date.
      properties:
        date:
          type: string
          format: date
          description: The date the bookings fall on.
          example: '2026-04-12'
        items:
          type: array
          description: Bookings on this date, sorted by start time.
          items:
            $ref: '#/components/schemas/OrderItineraryBooking'
      required:
        - date
        - items
    OrderItineraryGuestBucket:
      title: OrderItineraryGuestBucket
      type: object
      additionalProperties: false
      description: A guest's slice of an order itinerary, grouped by date.
      properties:
        guests:
          type: array
          description: Names of the guests included in this bucket.
          items:
            type: string
            example: Jane Doe
        items:
          type: array
          description: One entry per date the guest(s) have bookings on.
          items:
            $ref: '#/components/schemas/OrderItineraryDay'
      required:
        - guests
        - items
    OrderLedgerLine:
      title: OrderLedgerLine
      description: |
        A single ledger entry posted against an order. Ledger lines are
        the source of truth for revenue, payment and tax reporting; each
        line carries the monetary impact of one action against the order.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the ledger line.
        type:
          type: string
          description: |
            The kind of posting — for example `revenue`, `payment`,
            `refund`, `redemption`. Drives how the line is rolled up in
            reports.
          example: revenue
        status:
          type: string
          description: |
            The lifecycle status of the line. `final` is the only value
            callers should treat as authoritative; non-final lines are
            provisional and may change before close-of-day.
          example: final
        description:
          type: string
          nullable: true
          description: |
            Human-readable description of what the line represents — for
            example the offering name for revenue postings, or the
            payment processor for payment postings.
        gross_amount:
          type: integer
          description: |
            The gross amount of the line in the lowest denomination of
            the order's currency (e.g. pennies for `GBP`).
          example: 12000
        net_amount:
          type: integer
          description: |
            The net amount of the line — `gross_amount` minus tax — in
            the lowest denomination of the order's currency.
          example: 10000
        revenue_centre:
          type: string
          nullable: true
          description: |
            The revenue centre this line is attributed to. May be a
            Trybe system code (e.g. `treatments`, `retail`,
            `service_charge`) or a site-specific code.
          example: treatments
        revenue_centre_name:
          type: string
          nullable: true
          description: |
            Human-friendly label for the revenue centre. For Trybe
            system codes this is a localised name; for site-specific
            codes it falls back to the code itself.
          example: Treatments
        payment_processor:
          type: string
          nullable: true
          description: |
            For payment-related lines, the processor used (e.g.
            `stripe`, `adyen`, `manual`, `pms_folio`).
          example: stripe
        payment_processor_friendly:
          type: string
          nullable: true
          description: |
            Human-friendly version of `payment_processor`.
          example: Stripe
        mapped_value:
          type: string
          nullable: true
          description: |
            When a PMS or accounting integration maps the revenue centre
            to its own code, the mapped value is surfaced here. Omitted
            when no mapping applies.
        ledger_date:
          type: string
          format: date-time
          description: |
            The date the posting was recorded against the ledger. Used
            for reporting in operational time.
        revenue_date:
          type: string
          format: date-time
          description: |
            The business date the revenue should be recognised against.
            May differ from `ledger_date` for postings made after
            revenue recognition cut-off.
        currency:
          $ref: '#/components/schemas/properties_currency'
        payable:
          type: object
          nullable: true
          description: |
            Summary of the entity being charged — typically the order
            itself for revenue/redemption lines, or a `Payment` for
            payment/refund lines.
          additionalProperties: true
        causer:
          type: object
          nullable: true
          description: |
            Summary of the user or system process that triggered the
            posting. `null` for postings made by automated background
            jobs that aren't attributable to a single actor.
          additionalProperties: true
        created_at:
          $ref: '#/components/schemas/createdAt'
      required:
        - id
        - type
        - status
        - description
        - gross_amount
        - net_amount
        - revenue_centre
        - revenue_centre_name
        - payment_processor
        - payment_processor_friendly
        - ledger_date
        - revenue_date
        - currency
        - payable
        - causer
        - created_at
    OrderLedgerLinePosting:
      title: OrderLedgerLinePosting
      description: |
        A record of a ledger-line being forwarded to the site's PMS
        integration. Captures the integration name, the status of the
        posting, the amount posted and any processor-specific reference
        needed for reconciliation.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the posting record.
        integration:
          type: string
          description: |
            The PMS integration the posting was sent to (e.g. `mews`,
            `guestline`, `opera`).
          example: mews
        status:
          type: string
          description: |
            Where in the integration lifecycle the posting sits.
            `pending` postings haven't been confirmed by the PMS yet;
            `posted` postings have been acknowledged; `failed`
            postings need operator intervention.
          enum:
            - pending
            - posted
            - failed
          example: posted
        amount:
          type: integer
          description: |
            The amount posted, in the lowest denomination of the
            order's currency.
          example: 12000
        currency:
          $ref: '#/components/schemas/properties_currency'
        external_reference:
          type: string
          nullable: true
          description: |
            The PMS's own identifier for the posting, used by
            reconciliation jobs to match a Trybe ledger line to a PMS
            folio entry.
        processor_data:
          type: object
          additionalProperties: true
          nullable: true
          description: |
            Integration-specific metadata captured at posting time
            (HTTP response codes, folio IDs, error messages).
        created_at:
          $ref: '#/components/schemas/createdAt'
      required:
        - id
        - integration
        - status
        - amount
        - currency
        - external_reference
        - created_at
    OrderReceiptDocument:
      title: OrderReceiptDocument
      description: |
        A fiscal receipt document generated from an order's ledger lines.
        Shape varies by integration; common fields are surfaced here and
        integration-specific extras come through under `processor_data`.
      type: object
      additionalProperties: true
      properties:
        type:
          type: string
          description: |
            The kind of document produced — typically `json` for
            structured payloads or `html` for HTML receipts. When
            `html`, the same body is also available as a `text/html`
            response when the caller opts in via `Accept`.
          example: json
        content:
          type: object
          additionalProperties: true
          description: |
            The structured receipt body. Shape is determined by the
            site's fiscal-receipt integration; treat as opaque unless
            the integration is known. Always present for `json`
            documents.
          nullable: true
        html:
          type: string
          nullable: true
          description: |
            The HTML body of the receipt. Present when the document
            `type` is `html`.
        processor_data:
          type: object
          additionalProperties: true
          description: |
            Integration-specific metadata (signing certificates,
            sequence numbers, generated PDF URLs, etc.).
          nullable: true
      required:
        - type
    RmtReceiptDocument:
      title: RmtReceiptDocument
      description: |
        A Registered Massage Therapist (RMT) receipt document generated from an
        order's ledger lines. Only produced for Canadian sites.
      type: object
      additionalProperties: true
      properties:
        type:
          type: string
          description: |
            The kind of document produced — typically `json` for structured
            payloads or `html` for HTML receipts. When `html`, the same body is
            also available as a `text/html` response when the caller opts in via
            `Accept`.
          example: json
        contents:
          type: string
          nullable: true
          description: |
            The rendered HTML body of the receipt. Present when the document
            `type` is `html`.
        filename:
          type: string
          nullable: true
          description: The suggested filename for the receipt document, if applicable.
        url:
          type: string
          nullable: true
          description: A URL pointing to the receipt document, if applicable.
      required:
        - type
    TaxReceiptDocument:
      title: TaxReceiptDocument
      description: |
        A tax receipt document generated from an order's ledger lines.
      type: object
      additionalProperties: true
      properties:
        type:
          type: string
          description: |
            The kind of document produced — typically `json` for structured
            payloads or `html` for HTML receipts. When `html`, the same body is
            also available as a `text/html` response when the caller opts in via
            `Accept`.
          example: json
        contents:
          type: string
          nullable: true
          description: |
            The rendered HTML body of the receipt. Present when the document
            `type` is `html`.
        filename:
          type: string
          nullable: true
          description: The suggested filename for the receipt document, if applicable.
        url:
          type: string
          nullable: true
          description: A URL pointing to the receipt document, if applicable.
      required:
        - type
    OrderRefundableItemGuest:
      title: OrderRefundableItemGuest
      description: A guest associated with a refundable order item.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
        name:
          type: string
          nullable: true
        first_name:
          type: string
          nullable: true
        last_name:
          type: string
          nullable: true
      required:
        - id
    OrderRefundableItemRevenue:
      title: OrderRefundableItemRevenue
      description: Revenue attribution for a refundable order item.
      type: object
      additionalProperties: false
      properties:
        revenue_centre:
          type: string
        gross_revenue:
          type: integer
          description: Gross revenue in the lowest denomination of the order currency.
      required:
        - revenue_centre
        - gross_revenue
    OrderRefundableItem:
      title: OrderRefundableItem
      description: |
        A line on an order that has refundable balance remaining.
        Includes both standard order items and synthetic entries for
        service charge / tip components when they're positive.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: |
            Identifier for the refundable line. For order items this is
            the basket item object-id. For service-charge and tip lines
            this is the fixed key `service_charge` or `tip` — the same
            value used as the create-refund allocation `item_id`.
          example: tip
        offering_type:
          type: string
          nullable: true
          description: |
            Offering type for order items, or the fixed key `service_charge`
            / `tip` for synthetic lines.
        offering_id:
          type: string
          nullable: true
          description: Offering id for order items; null for synthetic lines.
        offering_name:
          type: string
          nullable: true
          description: |
            Human-readable label for the line — the offering name for
            items, `Service charge` / `Tip` for synthetic lines.
        item_date:
          type: string
          format: date
          nullable: true
          description: Date associated with the item (booking start or order submitted date).
        refunded_at:
          type: string
          format: date-time
          nullable: true
          description: |
            When a refund allocation against this line was last completed.
            Used by the tip modal to show tip-refund history.
        guests:
          type: array
          description: Guests attached to the order item (empty for tip / service charge).
          items:
            $ref: '#/components/schemas/OrderRefundableItemGuest'
        total_cost:
          type: integer
          description: Original line total in the lowest denomination of the order currency.
        refunded_amount:
          type: integer
          description: Amount already refunded against this line (pending + complete).
        refundable_amount:
          type: integer
          description: |
            The amount that can still be refunded, in the lowest
            denomination of the order's currency.
          example: 5000
        revenues:
          type: array
          items:
            $ref: '#/components/schemas/OrderRefundableItemRevenue'
      required:
        - id
        - offering_name
        - refunded_amount
        - refundable_amount
    OrderRevenueTax:
      title: OrderRevenueTax
      description: A single tax-rate component contributing to an order's revenue line.
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          description: The tax rate's display name.
          example: VAT (20%)
        rate:
          type: number
          description: The decimal tax rate (e.g. `0.2` for 20%).
          example: 0.2
        amount:
          type: integer
          description: |
            The tax amount in the lowest denomination of the order's
            currency.
          example: 2000
      required:
        - name
        - rate
        - amount
    OrderRevenue:
      title: OrderRevenue
      description: |
        Revenue contribution from a single revenue centre on an order.
        Gross and net amounts are in the lowest denomination of the
        order's currency; `taxes` enumerates the per-rate tax amounts
        that bridge net to gross.
      type: object
      additionalProperties: false
      properties:
        revenue_centre:
          type: string
          description: |
            The revenue centre code this entry rolls up. May be a Trybe
            system code (e.g. `treatments`, `retail`, `service_charge`)
            or a site-specific code defined in the organisation's
            revenue-centre setup.
          example: treatments
        revenue_centre_name:
          type: string
          description: |
            Human-friendly label for the revenue centre. For Trybe
            system codes this is a localised name; for site-specific
            codes it falls back to the code itself.
          example: Treatments
        gross_amount:
          type: integer
          description: |
            Gross revenue from this centre, in the lowest denomination
            of the order's currency.
          example: 12000
        net_amount:
          type: integer
          description: |
            Net revenue (gross minus tax) from this centre.
          example: 10000
        taxes:
          type: array
          description: |
            The tax components that make up the gross-to-net delta.
            Empty for tax-free centres.
          items:
            $ref: '#/components/schemas/OrderRevenueTax'
      required:
        - revenue_centre
        - revenue_centre_name
        - gross_amount
        - net_amount
        - taxes
    PractitionerRotaForDate:
      title: PractitionerRotaForDate
      description: |
        A `PractitionerRotaForDate` is the resolved working schedule for a
        single date for a single practitioner. It blends the regular rota
        (a recurring weekly pattern) with any ad-hoc custom availability
        rules that override that pattern for the requested day.

        The shape is intended for a date-picker / day-view UI: callers
        show the rules under `for_date.rules_for_date`, falling back to
        `for_date.rota_availability_rules` when no custom overrides exist.
      type: object
      additionalProperties: false
      required:
        - data
        - for_date
      properties:
        data:
          $ref: '#/components/schemas/PractitionerRota'
          nullable: true
          description: |
            The recurring rota that covers the requested date, if any.
            `null` when the practitioner has no rota covering the date
            — in that case `for_date.rota_availability_rules` is empty
            and any availability comes entirely from custom rules.
        for_date:
          title: PractitionerRotaForDateDetails
          type: object
          additionalProperties: false
          required:
            - date
            - week_number
            - rules_for_date
            - rota_availability_rules
            - custom_rules
          properties:
            date:
              type: string
              format: date
              description: The ISO 8601 date the rules describe, in the practitioner's timezone.
              example: '2026-06-01'
            week_number:
              type: integer
              nullable: true
              description: |
                1-indexed week number within the rota cycle that this date
                falls into. `null` when there is no covering rota. Combined
                with the rota's `scheduling_week_interval` this lets callers
                highlight which week of a multi-week pattern is active.
              example: 1
            rules_for_date:
              type: string
              description: |
                Which set of rules is authoritative for this date —
                `custom_rules` when at least one custom availability rule
                covers the date (so it overrides the rota),
                `rota_availability_rules` when the regular rota applies
                unmodified.
              enum:
                - custom_rules
                - rota_availability_rules
            rota_availability_rules:
              type: array
              description: |
                The rota's recurring rules that match this specific date.
                Empty when no rota covers the date.
              items:
                title: PractitionerRotaForDateRotaRule
                type: object
                additionalProperties: false
                required:
                  - time_from
                  - time_to
                properties:
                  time_from:
                    type: string
                    description: The start time of the availability window in `HH:MM` 24-hour format.
                    example: '09:00'
                  time_to:
                    type: string
                    description: The end time of the availability window in `HH:MM` 24-hour format.
                    example: '17:00'
                  room_id:
                    type: string
                    format: object-id
                    nullable: true
                    description: The room the practitioner is assigned to during this window, if any.
            custom_rules:
              type: array
              description: |
                Custom availability rules that override the rota for this
                date. May contain both `is_available: true` rules (extra
                working windows) and `is_available: false` rules (blocked
                windows).
              items:
                $ref: '#/components/schemas/PractitionerCustomAvailability'
    ShopAppointmentTag:
      title: ShopAppointmentTag
      description: |
        An `AppointmentTag` exposed via the storefront listing endpoint.
        Tags are short labels (e.g. "couples", "mens") used by the
        booking UI to filter appointment types.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the tag.
        name:
          type: string
          description: Display name shown to customers.
        color:
          type: string
          nullable: true
          description: Hex colour used to highlight tagged items in the UI.
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation this tag belongs to.
      required:
        - id
        - name
        - organisation_id
    ShopCategory:
      title: ShopCategory
      description: |
        A `Category` exposed via the storefront listing endpoint —
        organisation-level groupings used to bucket offerings on the
        booking site (e.g. "Spa", "Salon", "Fitness").
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the category.
        name:
          type: string
          description: Display name shown to customers.
        slug:
          type: string
          nullable: true
          description: URL-friendly slug used in deep links.
        description:
          type: string
          nullable: true
          description: Marketing description shown on the category landing page.
        image_url:
          type: string
          format: uri
          nullable: true
          description: Hero image URL for the category.
        order:
          type: integer
          description: Sort order within the storefront listing.
        organisation_id:
          type: string
          format: uuid
          description: ID of the organisation this category belongs to.
      required:
        - id
        - name
        - organisation_id
    ShopPractitioner:
      title: ShopPractitioner
      description: |
        A `Practitioner` exposed via the storefront listing endpoint —
        only the public-facing fields are returned.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the practitioner.
        name:
          type: string
          description: Display name (`first_name + last_name`).
        image_url:
          type: string
          format: uri
          nullable: true
          description: Public profile image.
        bio:
          type: string
          nullable: true
          description: Long-form biography shown on the practitioner profile.
        title:
          type: string
          nullable: true
          description: Job title shown next to the practitioner name.
        pronouns:
          type: string
          nullable: true
          description: Self-declared pronouns.
      required:
        - id
        - name
    VoucherTypeSummary:
      title: VoucherTypeSummary
      description: |
        Lightweight summary of a `VoucherType` — just `id` and `name`.
        Returned by the ordering endpoints (`GET /shop/voucher-types/order`
        and `PUT /shop/voucher-types/order`) where the full payload would
        be wasteful.
      type: object
      additionalProperties: false
      required:
        - id
        - name
      properties:
        id:
          type: string
          format: object-id
          description: The ID of the voucher type.
          example: 5dcb47800000000000000000
        name:
          type: string
          description: The display name of the voucher type.
          example: £50 voucher
    CrossOrganisationCouponCode:
      title: CrossOrganisationCouponCode
      description: |
        The cross-organisation view of a `CouponCode`. Returned by
        `GET /shop/coupon-codes` when looking up a code by string across
        every coupon the calling user has visibility on. Includes the
        `organisation_id` the code belongs to so the consumer can scope
        follow-up requests; omits the per-customer pre-allocation fields
        that are only available on the nested `/shop/coupons/{couponId}/codes/{couponCodeId}` view.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: object-id
          description: Unique identifier for the coupon code.
          example: 5f1234567890abcdef123456
        coupon_id:
          type: string
          format: object-id
          description: ID of the parent `Coupon`.
          example: 5f1234567890abcdef123456
        code:
          type: string
          description: The redemption code customers type at checkout.
          example: SUMMER2026
        valid_from_date:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO 8601 timestamp from which the code is redeemable. Null =
            valid immediately.
          example: '2026-06-01T00:00:00+00:00'
        valid_to_date:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO 8601 timestamp after which the code expires. Null = no
            expiry.
          example: '2026-08-31T23:59:59+00:00'
        multi_use:
          type: boolean
          description: |
            When true, the same code can be redeemed multiple times (once
            per customer). When false, the code burns after the first
            redemption.
          example: false
        organisation_id:
          type: string
          format: uuid
          description: |
            UUID of the organisation the code's coupon belongs to. Useful
            for routing follow-up calls to the right
            `/shop/organisations/{organisationId}/...` resource.
          example: 00000000-0000-0000-0000-000000000000
      required:
        - id
        - coupon_id
        - code
        - multi_use
        - organisation_id
    OfferingAvailabilityDay:
      title: OfferingAvailabilityDay
      description: |
        Per-day availability summary for a single calendar day in a
        monthly view. Returned by `GET /shop/offering-availability` for
        every day in the targeted month.
      type: object
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: ISO 8601 calendar date in the offering's timezone.
          example: '2026-05-23'
        is_available:
          type: boolean
          description: |
            Whether the offering has at least one bookable window left
            anywhere within the day, factoring in `unavailable`
            availability rules.
        is_offered:
          type: boolean
          description: |
            Whether any `available` rule covers the day at all. If false,
            the offering is not sold on this date regardless of
            `is_available`.
      required:
        - date
        - is_available
        - is_offered
    OrderIntakeForm:
      title: OrderIntakeForm
      description: |
        Per-guest intake-form status for an `Order`. One entry per guest +
        form combination: the response includes already-completed forms
        (with a `visit_intake_form_id` and `completed_at`), pending forms
        the guest still needs to fill in (with an `intake_form_url` they
        can be linked to), and rolled-forward mandatory waivers that the
        guest completed on a previous visit.
      type: object
      additionalProperties: false
      properties:
        basket_id:
          type: string
          format: object-id
          description: |
            ID of the `Basket`/`Order` the intake form belongs to. May
            differ from the `orderIntakeFormId` in the path when surfacing
            a previously-completed mandatory waiver rolled forward from an
            earlier order.
          example: 5dcb47800000000000000009
        visit_intake_form_id:
          type: string
          format: object-id
          nullable: true
          description: |
            ID of the completed `VisitIntakeForm` record. `null` when the
            form has not been filled in yet.
          example: 5dcb47800000000000001111
        guest_id:
          type: string
          format: object-id
          nullable: true
          description: |
            ID of the guest the form belongs to. `null` for orphan intake
            forms that don't link back to any guest on the current order.
          example: 5dcb47800000000000002222
        name:
          type: string
          description: |
            Guest's full display name. Empty string when the guest has no
            associated name (e.g. on orphan forms).
          example: Jane Doe
        first_name:
          type: string
          description: Guest's first name (empty string when unavailable).
          example: Jane
        last_name:
          type: string
          description: Guest's last name (empty string when unavailable).
          example: Doe
        intake_form_url:
          type: string
          nullable: true
          format: uri
          description: |
            Public URL the guest can visit to complete the intake form.
            `null` once the form has been filled in.
          example: https://shop.try.be/intake-form?basket_id=5dcb47800000000000000009&token=abc
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO 8601 timestamp at which the guest completed the form.
            `null` while pending.
          example: '2026-05-23T11:00:00+00:00'
        anonymised_at:
          type: string
          format: date-time
          nullable: true
          description: |
            ISO 8601 timestamp at which the completed form's personal data
            was anonymised by Trybe's retention policy. `null` while the
            data is still intact.
        requires_intake_form:
          type: boolean
          description: |
            Whether the guest is required to fill this form in for the
            order. False once `visit_intake_form_id` is set.
          example: true
        mandatory_waiver:
          type: boolean
          description: |
            Whether this is a mandatory waiver — the type of intake form
            that, once completed by a customer, rolls forward to subsequent
            orders until the waiver lapses.
          example: false
      required:
        - basket_id
        - visit_intake_form_id
        - guest_id
        - name
        - first_name
        - last_name
        - intake_form_url
        - completed_at
        - anonymised_at
        - requires_intake_form
        - mandatory_waiver
    ScheduledAvailabilityWindow:
      title: ScheduledAvailabilityWindow
      description: |
        A resolved availability window for a practitioner or room. The
        endpoint returns a flat list mixing regular (rota-derived) windows
        and custom-override windows; each row carries an
        `availability_type` so consumers can tell them apart.
      type: object
      additionalProperties: false
      properties:
        practitioner_id:
          type: string
          format: object-id
          description: |
            ID of the practitioner the window belongs to. Present on
            practitioner-scoped responses; omitted on room responses.
        room_id:
          type: string
          format: object-id
          description: |
            ID of the room the window belongs to. Present on room-scoped
            responses; omitted on practitioner responses.
        date_time_from:
          type: string
          format: date-time
          description: ISO 8601 start of the window.
          example: '2026-05-23T09:00:00+00:00'
        date_time_to:
          type: string
          format: date-time
          description: ISO 8601 end of the window.
          example: '2026-05-23T17:00:00+00:00'
        is_available:
          type: boolean
          description: |
            True for available windows, false for explicit
            unavailable-override windows (only meaningful when
            `availability_type=custom`).
        availability_type:
          type: string
          description: |
            Whether the window came from the regular rota or a
            custom-availability override.
          enum:
            - regular
            - custom
        custom_availability_id:
          type: string
          format: object-id
          description: |
            ID of the `CustomAvailabilityRule` backing the window. Present
            only when `availability_type=custom`.
      required:
        - date_time_from
        - date_time_to
        - is_available
        - availability_type
    CheckInCustomer:
      title: CheckInCustomer
      type: object
      additionalProperties: false
      description: Summary details of the customer who checked in.
      properties:
        id:
          type: string
          format: uuid
          description: The customer ID associated with this check-in
          example: 000000-000000-000000-000000
        first_name:
          type: string
          description: The customer's first name
          example: John
        last_name:
          type: string
          description: The customer's last name
          example: Smith
        full_name:
          type: string
          description: The customer's full name
          example: John Smith
        email:
          type: string
          description: The customer's email address
          example: john@example.com
      required:
        - id
        - first_name
        - last_name
        - full_name
        - email
    CheckInMethod:
      title: CheckInMethod
      type: object
      additionalProperties: false
      description: Details of the method used to record the check-in.
      properties:
        name:
          type: string
          description: The name of the method used to create this check-in
          example: Scanned
      required:
        - name
    CheckIn:
      title: CheckIn
      type: object
      additionalProperties: false
      description: |
        A `CheckIn` represents an instance of a customer arriving at a site. Check-ins are typically created when a customer scans an associated barcode, taps a wearable on a Gantner reader, or is checked in manually via the Trybe app.
      properties:
        id:
          type: string
          description: The ID of this check-in
          example: 000000-000000-000000-000000
        customer:
          $ref: '#/components/schemas/CheckInCustomer'
        membership_id:
          type: string
          description: The membership ID associated with this check-in
          example: 000000-000000-000000-000000
        site_id:
          type: string
          description: The site ID where this check-in happened
          example: 000000-000000-000000-000000
        method:
          $ref: '#/components/schemas/CheckInMethod'
        source:
          type: string
          nullable: true
          description: |
            Where the check-in/out originated: `app` (staff app check-in
            button), `kiosk` (self-service kiosk), or `gantner` (Gantner
            access gate). Null for records created before source tracking
            existed.
          enum:
            - app
            - kiosk
            - gantner
            - null
          example: kiosk
        checked_in_at:
          type: string
          description: The datetime when this check-in happened
          format: date-time
          example: '2021-01-01T00:00:00.000Z'
          nullable: true
        checked_out_at:
          type: string
          description: The datetime when this check-out happened
          format: date-time
          example: '2021-01-01T00:00:00.000Z'
          nullable: true
      required:
        - id
        - customer
        - membership_id
        - site_id
        - method
        - source
        - checked_in_at
        - checked_out_at
    CustomerAddress:
      title: CustomerAddress
      type: object
      additionalProperties: false
      description: |
        A `CustomerAddress` represents a postal address belonging to a `Customer`. Customers may have any number of addresses (home, work, billing, etc.) and one or more of these can be referenced when placing orders or generating invoices.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the address
          example: 000000-000000-000000-000000
        name:
          type: string
          description: The name of the address
          example: Home
        address_line_1:
          type: string
          description: The first address line
          example: 123 Fake Street
        address_line_2:
          type: string
          description: The second address line
          example: Some Building
          nullable: true
        city:
          type: string
          example: London
          nullable: true
        county:
          type: string
          example: London
          nullable: true
        country:
          type: string
          example: United Kingdom
          nullable: true
        country_code:
          type: string
          description: The ISO3166-2 country code for the country of this address
          example: GB
          nullable: true
        postcode:
          type: string
          example: E14 1AA
          nullable: true
      required:
        - id
        - name
        - address_line_1
        - address_line_2
        - city
        - county
        - country
        - country_code
        - postcode
    CustomerCredit:
      title: CustomerCredit
      type: object
      additionalProperties: false
      description: |
        A `CustomerCredit` represents a coupon credit issued to a customer. Credits can be issued automatically as part of a membership benefit or manually issued as a one-off (e.g. as a goodwill gesture). Each credit references the underlying `Coupon` that defines what the credit entitles the customer to.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the credit
          example: 000000-000000-000000-000000
        coupon_name:
          type: string
          description: The name of the underlying coupon
          example: Free 30 minute massage
        coupon_description:
          type: string
          description: The description of the underlying coupon
          example: Enjoy a free 30 minute massage as a thanks for being a loyal member
        multi_use:
          type: boolean
          description: Whether this credit can be used multiple times
          example: true
        customer_id:
          type: string
          format: uuid
          description: The ID of the customer this credit belongs to
          example: 000000-000000-000000-000000
        membership_id:
          type: string
          format: uuid
          description: The ID of the membership this credit relates to, if applicable
          example: 000000-000000-000000-000000
          nullable: true
        coupon_code:
          type: string
          description: The coupon code which relates to this credit
        revenue:
          type: integer
          description: The amount of revenue that should be allocated when this credit is redeemed, in the smallest unit of currency.
          example: 2495
        issued_at:
          type: string
          format: date-time
          description: The date and time which the credit was issued
          example: '2021-01-01T00:00:00.000Z'
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: |
            The date and time which the credit expires. If null, the credit does not expire.
          example: '2021-01-01T00:00:00.000Z'
        redeemed_at:
          type: string
          format: date-time
          nullable: true
          description: |
            The date and time which the credit was redeemed. If null, the credit hasn't been redeemed yet.
          example: '2021-01-01T00:00:00.000Z'
        revoked_at:
          type: string
          format: date-time
          nullable: true
          description: |
            The date and time which the credit was revoked. If null, the credit hasn't been revoked.
      required:
        - id
        - coupon_name
        - coupon_description
        - multi_use
        - customer_id
        - membership_id
        - coupon_code
        - revenue
        - issued_at
        - expires_at
        - redeemed_at
        - revoked_at
    CustomerMarketingPreferenceOptIn:
      title: CustomerMarketingPreferenceOptIn
      type: object
      additionalProperties: false
      description: |
        A `CustomerMarketingPreferenceOptIn` represents the opt-in/out state of a single marketing preference for a customer, including the timestamps of the most recent change.
      properties:
        id:
          type: string
          description: The ID of the marketing preference
          example: 5dcb47800000000000000110
        marketing_preference:
          $ref: '#/components/schemas/MarketingPreference'
        opted_in:
          type: boolean
          description: Whether the customer is opted in to this marketing preference
          example: true
        opted_in_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time at which the customer opted in to this preference
          example: '2020-02-24T12:00:00+00:00'
        opted_out_at:
          type: string
          format: date-time
          nullable: true
          description: The date and time at which the customer opted out of this preference
          example: '2020-02-24T12:00:00+00:00'
        is_archived:
          type: boolean
          description: True if the marketing preference is archived
      required:
        - id
        - marketing_preference
        - opted_in
        - opted_in_at
        - opted_out_at
        - is_archived
    CustomerNoteAuthor:
      title: CustomerNoteAuthor
      type: object
      additionalProperties: false
      description: The user who created or last updated this note.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the user
        first_name:
          type: string
          description: The first name of the user
        last_name:
          type: string
          description: The last name of the user
      required:
        - id
        - first_name
        - last_name
    CustomerNote:
      title: CustomerNote
      type: object
      additionalProperties: false
      description: |
        A `CustomerNote` is free-form text recorded against a customer by a staff member, used for capturing context that should follow the customer across visits (e.g. dietary requirements, preferences, behavioural flags).
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the note
        note:
          type: string
          description: The contents of the note
        author:
          $ref: '#/components/schemas/CustomerNoteAuthor'
        created_at:
          type: string
          format: date-time
          description: The date and time that the note was created
        updated_at:
          type: string
          format: date-time
          description: The date and time that the note was last updated
      required:
        - id
        - note
        - author
        - created_at
        - updated_at
    schemas_Label-2:
      title: Label
      type: object
      additionalProperties: false
      description: |
        A `Label` is an organisation-wide tag that can be attached to customers, orders, and other resources to categorise them for reporting and filtering purposes.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the label
          example: 000000-000000-000000-000000
        value:
          type: string
          description: The name of the label
          example: VIP
        colour:
          type: string
          description: A hex colour code excluding the preceding \# which this label will be rendered as.
          example: ff6634
        organisation_id:
          type: string
          format: uuid
          description: The organisation which this label belongs to
          example: 000000-000000-000000-000000
        created_at:
          type: string
          format: date-time
          description: The datetime which the label was created
          example: '2021-01-01T00:00:00.000Z'
        updated_at:
          type: string
          format: date-time
          description: The datetime which the label was last updated
          example: '2021-01-01T00:00:00.000Z'
      required:
        - id
        - value
        - colour
        - organisation_id
        - created_at
        - updated_at
    MembershipRateLocaleStrings:
      title: MembershipRateLocaleStrings
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          nullable: true
          description: The localised name for this membership rate in the given locale.
          example: Monthly Spa Membership
      required:
        - name
    MembershipRateTotals:
      title: MembershipRateTotals
      type: object
      additionalProperties: false
      description: |
        A breakdown of how much a customer will be charged for a membership rate over a given
        period, including any joining fee, pro-rata fee and recurring monthly fee.
      properties:
        total_price:
          title: MembershipRateTotalsTotalPrice
          type: object
          additionalProperties: false
          description: |
            The total cost of the membership for the given period of time including the
            monthly fee, pro-rata amounts and a joining fee if applicable.
          properties:
            amount:
              type: integer
              description: The amount as an integer of the smallest unit (eg pence)
              example: 6000
            currency:
              type: string
              description: The currency which the amount is in, uppercase, in the ISO4217 format
              example: GBP
          required:
            - amount
            - currency
        breakdowns:
          title: MembershipRateTotalsBreakdowns
          type: object
          additionalProperties: false
          description: An object explaining how the `total_price` is broken down
          properties:
            joining_fee:
              title: MembershipRateTotalsJoiningFee
              type: object
              additionalProperties: false
              description: The joining fee that is payable to start the membership
              properties:
                amount:
                  type: integer
                  description: The amount as an integer of the smallest unit (eg pence)
                  example: 1000
                currency:
                  type: string
                  description: The currency which the amount is in, uppercase, in the ISO4217 format
                  example: GBP
              required:
                - amount
                - currency
            pro_rata_fee:
              title: MembershipRateTotalsProRataFee
              type: object
              additionalProperties: false
              description: |
                If the given `start_date` is not the 1st of any month, a pro-rata fee will be charged
                which is calculated as the monthly fee divided by the number of days between the
                `start_date` and the 1st of the following month.
              properties:
                amount:
                  type: integer
                  description: The amount as an integer of the smallest unit (eg pence)
                  example: 1500
                currency:
                  type: string
                  description: The currency which the amount is in, uppercase, in the ISO4217 format
                  example: GBP
              required:
                - amount
                - currency
            monthly_fee:
              title: MembershipRateTotalsMonthlyFee
              type: object
              additionalProperties: false
              description: The amount which will be charged per month
              properties:
                amount:
                  type: integer
                  description: The amount as an integer of the smallest unit (eg pence)
                  example: 3000
                currency:
                  type: string
                  description: The currency which the amount is in, uppercase, in the ISO4217 format
                  example: GBP
              required:
                - amount
                - currency
        summary_lines:
          type: array
          description: |
            An array of strings explaining how the customer will be charged, and details about
            when their membership will start and end.
          items:
            type: string
            example: Your first Direct Debit payment will be taken on **23rd June 2023** for **£30.00**.
      required:
        - total_price
        - breakdowns
        - summary_lines
    StripeCheckoutSession:
      title: StripeCheckoutSession
      type: object
      additionalProperties: false
      description: |
        A Stripe Checkout Session for collecting either Direct Debit mandate details or a
        joining-fee/pro-rata payment as part of the membership signup flow.
      properties:
        status:
          type: string
          description: The status of the membership
          example: needs_dd_mandate
        account_id:
          type: string
          description: |
            Stripe Connect account ID that owns the Checkout Session.
            Pass this to `stripe.redirectToCheckout({ stripeAccount })`
            in the client so the redirect is scoped to the right merchant
            account. Tenants on a single Stripe account can ignore it.
          example: acct_1Jmwv72UMaxwwwup
        url:
          type: string
          description: The URL to get to the Stripe Checkout session
        stripe_session_id:
          type: string
          description: The Stripe Checkout session ID
          example: si_1234567890
        rate_price:
          title: StripeCheckoutSessionRatePrice
          type: object
          additionalProperties: false
          description: The price of the membership rate
          properties:
            amount:
              type: integer
              description: The amount as an integer of the smallest unit (eg pence)
              example: 1000
            currency:
              type: string
              description: The currency which the amount is in, uppercase, in the ISO4217 format
              example: GBP
          required:
            - amount
            - currency
        rate_frequency:
          type: string
          description: |
            The frequency that this membership is billed.
            The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1M
      required:
        - status
        - account_id
        - url
        - stripe_session_id
        - rate_price
        - rate_frequency
    MembershipMember:
      title: MembershipMember
      type: object
      additionalProperties: false
      description: A `Customer` who is a member of a `Membership`, along with their lead-member status and unique membership number.
      properties:
        membership_number:
          type: string
          description: The membership number of the member
        customer:
          $ref: '#/components/schemas/Customer'
        is_lead:
          type: boolean
          description: Whether this customer is the lead customer on the membership
      required:
        - membership_number
        - customer
        - is_lead
    NextBillingDetails:
      title: NextBillingDetails
      type: object
      additionalProperties: false
      description: Summary of the next billing event for a membership.
      properties:
        date:
          type: string
          format: date
          description: |
            This is the next billing date for a membership. If this value is null, the membership will
            not be active on the next billing date.
          nullable: true
        amount:
          type: integer
          description: |
            This is the next billing amount for a membership, as an integer of the smallest unit (e.g. pence).
            If this value is null, the membership will not be active on the next billing date.
          nullable: true
        currency:
          type: string
          description: The currency which all monetary values of this rate are in, uppercase, in the ISO4217 format
          example: GBP
      required:
        - date
        - amount
        - currency
    SubsequentBillingDetails:
      title: SubsequentBillingDetails
      type: object
      additionalProperties: false
      description: Summary of the subsequent billing event for a membership (the one after `next_billing_date`).
      properties:
        date:
          type: string
          format: date
          description: |
            This is the subsequent billing date for a membership. If this value is null, the membership will
            not be active on the subsequent billing date.
          nullable: true
        amount:
          type: integer
          description: |
            This is the subsequent billing amount for a membership, as an integer of the smallest unit (e.g. pence).
            If this value is null, the membership will not be active on the subsequent billing date.
          nullable: true
        currency:
          type: string
          description: The currency which all monetary values of this rate are in, uppercase, in the ISO4217 format
          example: GBP
      required:
        - date
        - amount
        - currency
    Subscription:
      title: Subscription
      type: object
      additionalProperties: false
      description: |
        A `Subscription` represents the authenticated user's opt-in to receive a particular
        notification (e.g. `failed_payments`, `expiring_soon`) for a specific `Site`.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the subscription
        site_id:
          type: string
          format: uuid
          description: The site ID which this subscription relates to
        notification_type:
          type: string
          description: The type of notification this subscription is for
          enum:
            - failed_payments
            - expiring_soon
            - new_signups
            - revoked_mandate
        created_at:
          type: string
          format: date-time
          description: The date-time when this subscription was created
        updated_at:
          type: string
          format: date-time
          description: The date-time when this subscription was last updated
      required:
        - id
        - site_id
        - notification_type
        - created_at
        - updated_at
    SignupToken:
      title: SignupToken
      type: object
      additionalProperties: false
      description: |
        A `SignupToken` permits a customer to sign up for a private `MembershipType` or
        non-default `MembershipRate`. Tokens carry an optional cap on how many times they can
        be used and can pre-populate customer details such as name and email.
      properties:
        id:
          type: string
          description: The ID of the signup token.
          example: 000000-000000-000000-000000
        membership_type_id:
          type: string
          description: The MembershipType this token allows signups as
          example: 000000-000000-000000-000000
        membership_rate_id:
          type: string
          description: The MembershipRate this token allows signups as. If omitted, the default rate of the given type will be used.
          example: 000000-000000-000000-000000
          nullable: true
        start_date:
          type: string
          description: The date which the membership should start
          format: date
          example: '2021-02-21'
          nullable: true
        end_date:
          type: string
          description: The date which the membership should end
          format: date
          example: '2022-02-21'
          nullable: true
        duration:
          type: string
          description: The duration of the membership as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
          example: P1M
        max_uses:
          type: integer
          nullable: true
          description: |
            The maximum number of times this signup token can be used. If null, it can be used an
            unlimited number of times. When the number of uses reaches the max_uses, it is soft-deleted.
        uses:
          type: integer
          description: The number of times this signup token has been used.
        first_name:
          type: string
          description: The first name of the customer this token allows signups as. If omitted, the customer can set a first name.
          nullable: true
          example: Dan
        last_name:
          type: string
          description: The last name of the customer this token allows signups as. If omitted, the customer can set a last name.
          nullable: true
        email:
          type: string
          description: The email of the customer this token allows signups as. If omitted, the customer can set an email.
          example: dan@try.be
          nullable: true
      required:
        - id
        - membership_type_id
        - membership_rate_id
        - start_date
        - end_date
        - max_uses
        - uses
    MobilePassCustomisation:
      title: MobilePassCustomisation
      type: object
      additionalProperties: false
      description: |
        Visual customisation for a site's mobile pass — Apple Wallet / Google Wallet — including
        the icon, logo, strip image and colour scheme. Each media reference points to a `Media`
        record uploaded via the media endpoints.
      properties:
        enabled:
          type: boolean
          description: Whether or not mobile passes are enabled for this site
        icon_id:
          type: string
          format: uuid
          description: The id of the icon
          example: 000000-000000-000000-000000
        icon:
          $ref: '#/components/schemas/Media'
        logo_id:
          type: string
          format: uuid
          description: The id of the logo
          example: 000000-000000-000000-000000
        logo:
          $ref: '#/components/schemas/Media'
        strip_id:
          type: string
          format: uuid
          description: The id of the strip image
          example: 000000-000000-000000-000000
        strip:
          $ref: '#/components/schemas/Media'
        background_colour:
          type: string
          description: A hex colour code excluding the preceding `#` for the background
        foreground_colour:
          type: string
          description: A hex colour code excluding the preceding `#` for the foreground
        label_colour:
          type: string
          description: A hex colour code excluding the preceding `#` for the labels
      required:
        - enabled
    Notification:
      type: object
      title: Notification
      description: |
        An in-product notification raised for a user — for example, a
        new order from an integration, a customer check-in, or a
        failing background job. Notifications are scoped to a site and
        carry a payload of action links for the recipient to follow.
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the notification.
          example: beddda88-947d-4bd8-8f0c-828b187f93b2
        title:
          type: string
          description: A short headline summarising the notification.
          example: An order was created by rezlynx
        type:
          type: string
          description: |
            The machine-readable type discriminator for the
            notification. Used by clients to group, filter, or render
            notifications.
          example: guestline_order_created
        subject_id:
          type: string
          description: The ID of the entity the notification is about (e.g. the order or visit ID).
          example: beddda88-947d-4bd8-8f0c-828b187f93b2
        subject_type:
          type: string
          description: The type of the entity referenced by `subject_id` (e.g. `Order`, `Visit`).
          example: Order
        site_id:
          type: string
          format: uuid
          description: The ID of the site this notification relates to.
          example: beddda88-947d-4bd8-8f0c-828b187f93b2
        created_at:
          type: string
          format: date-time
          example: '2019-01-15T11:00:00.000Z'
          description: The date and time the notification was created.
        read_at:
          type: string
          format: date-time
          nullable: true
          example: '2019-01-15T11:00:00.000Z'
          description: The date and time the notification was read, or `null` if still unread.
        acknowledged_by:
          type: object
          title: NotificationAcknowledgedBy
          nullable: true
          additionalProperties: false
          description: The user who acknowledged the notification, if any.
          properties:
            id:
              type: string
              format: uuid
              description: The ID of the user who acknowledged the notification.
              example: beddda88-947d-4bd8-8f0c-828b187f93b2
            name:
              type: string
              description: The display name of the user who acknowledged the notification.
              example: Jane Smith
        data:
          title: NotificationData
          type: object
          description: The notification payload — a free-form object whose shape depends on the notification `type`.
          additionalProperties: true
          properties: {}
        actions:
          type: array
          description: A list of follow-up actions the recipient can take.
          items:
            type: object
            title: NotificationAction
            additionalProperties: false
            properties:
              label:
                type: string
                description: The button label shown to the user.
                example: View order
              type:
                type: string
                description: The machine-readable action discriminator.
                example: view_order
              url:
                type: string
                description: The URL the action should open.
                example: https://app.try.be/orders/beddda88-947d-4bd8-8f0c-828b187f93b2
    InventoryAdjustment:
      type: object
      title: InventoryAdjustment
      description: |
        A single stock adjustment — a positive or negative change to the
        quantity of an inventory product at a location. Adjustments
        capture the reason (e.g. waste, transfer, sale) and the user
        who made the change so that stock movement can be audited.
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the adjustment.
          example: 10000000-0000-0000-0000-000000000000
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this adjustment belongs to.
          example: 20000000-0000-0000-0000-000000000000
        site_id:
          type: string
          format: uuid
          description: The ID of the site this adjustment belongs to.
          example: 30000000-0000-0000-0000-000000000000
        product_id:
          type: string
          format: uuid
          description: The ID of the product this adjustment is for.
          example: 30000000-0000-0000-0000-000000000000
        quantity:
          type: integer
          description: The amount of the adjustment, which may be positive or negative.
        reason_code:
          type: string
          description: A reason code for the adjustment, e.g. `waste` or `transfer`.
        reason_description:
          type: string
          description: A free-text reason for the adjustment.
        location_id:
          type: integer
          nullable: true
          description: The ID of the location the stock is moving from.
        created_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00.000Z'
          description: The date and time the adjustment was created.
      required:
        - product_id
        - quantity
    InventoryLocation:
      type: object
      title: InventoryLocation
      description: |
        A physical inventory location within a site — for example,
        "Treatment store", "Retail floor", or "Back of house". Locations
        are the bucket against which stock counts and adjustments are
        recorded; products can exist in multiple locations.
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the location.
          example: 10000000-0000-0000-0000-000000000000
        organisation_id:
          type: string
          format: uuid
          description: The ID of the organisation this location belongs to.
          example: 20000000-0000-0000-0000-000000000000
        site_id:
          type: string
          format: uuid
          description: The ID of the site this location belongs to.
          example: 30000000-0000-0000-0000-000000000000
        name:
          type: string
          maxLength: 100
          description: A display name for the location.
          example: Treatment store
        created_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00.000Z'
          description: The date and time the location was created.
        updated_at:
          type: string
          format: date-time
          example: '2019-01-15T12:00:00.000Z'
          description: The date and time the location was last updated.
      required:
        - name
    NotificationsMeta:
      type: object
      title: NotificationsMeta
      description: Pagination metadata for a notification list, extended with read/unread totals across the full result set.
      additionalProperties: false
      allOf:
        - $ref: '#/components/schemas/PaginationMeta'
        - title: NotificationsMetaExtras
          type: object
          additionalProperties: false
          properties:
            total_read:
              description: The number of notifications that have been read.
              type: integer
              example: 1
            total_unread:
              description: The number of notifications that have not been read.
              type: integer
              example: 1
    PersonalAccessToken:
      type: object
      title: PersonalAccessToken
      description: |
        A named personal-access token issued to a user, used to
        authenticate API calls in place of a username and password. The
        raw token value is only ever returned at the moment of creation
        via `createPersonalAccessToken`; subsequent reads expose only
        the token's metadata.
      additionalProperties: false
      properties:
        id:
          type: string
          description: |
            Stable identifier for the personal-access token. Use this to
            revoke the token later via `deletePersonalAccessToken`. The
            ID is safe to log; the raw secret is only ever returned at
            creation as `accessToken`.
          example: 27ebb191b5f4f2024b0c5671e580d6de2b03f6c48259753b01976807a14eb41e05f0b7def4593f5a
          readOnly: true
        name:
          type: string
          description: A human-readable label for the token, used to distinguish it from other tokens issued to the same user.
          example: Salesforce
        created_at:
          type: string
          format: date-time
          example: '2019-01-15T11:00:00.000Z'
          description: The date and time the personal access token was created.
          readOnly: true
      required:
        - name
    SiteTaxInfo:
      type: object
      title: SiteTaxInfo
      description: |
        Tax-registration and registered-address details for the legal
        entity behind a `Site`. Used on invoices, receipts, and tax
        reports to satisfy local invoicing requirements (VAT/GST numbers,
        registered company address).
      additionalProperties: false
      properties:
        tax_id:
          type: string
          description: The tax ID, ie the VAT number.
          example: GB 123 4567 89
        company_number:
          type: string
          nullable: true
          description: Company registration number, for example SIRET for French businesses
          example: '12345678901234'
        fr_naf_code:
          type: string
          nullable: true
          description: NAF code for French businesses
          example: 56.10A
        address_line_1:
          type: string
          description: The first address line of the registered company.
          example: 71 Aldwych
        address_line_2:
          type: string
          nullable: true
          description: The second address line of the registered company.
          example: WeWork
        city:
          type: string
          description: The city of the registered company.
          example: London
        county:
          type: string
          nullable: true
          description: The county of the registered company.
          example: London
        country:
          type: string
          description: The country of the registered company.
          example: United Kingdom
        postcode:
          type: string
          description: The postcode of the registered company.
          example: WC2B 4HN
      required:
        - tax_id
        - address_line_1
        - city
        - country
        - postcode
    UserOptions:
      type: object
      title: UserOptions
      description: |
        A free-form map of UI preferences for the authenticated user.
        Trybe stores user-supplied options such as default site picker
        selections, dismissed onboarding tips, table column preferences,
        and so on. Keys and values are arbitrary — clients should round-
        trip unknown keys without modifying them.
      additionalProperties: true
      properties: {}
    TwoFactorQrCode:
      type: object
      title: TwoFactorQrCode
      description: |
        A two-factor authentication QR code object. Contains the URL the
        authenticator app should be pointed at along with a pre-rendered
        SVG version of the QR code for display in the UI.
      additionalProperties: false
      properties:
        url:
          type: string
          description: The url-encoded `otpauth://` URI represented by the QR code.
          example: otpauth://totp/Trybe:jane@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Trybe
        svg:
          type: string
          description: An inline SVG rendering of the QR code, ready for embedding in HTML.
          example: <svg></svg>
      required:
        - url
        - svg
    TwoFactorRecoveryCodes:
      type: array
      title: TwoFactorRecoveryCodes
      description: A list of single-use recovery codes the user can use to authenticate if they lose access to their second factor.
      items:
        type: string
        description: A single-use recovery code.
    TwoFactorSecretKey:
      type: object
      title: TwoFactorSecretKey
      description: The two-factor authentication shared secret in base32 form. Use this if the user is configuring their authenticator by hand instead of scanning the QR code.
      additionalProperties: false
      properties:
        secretKey:
          type: string
          description: The base32-encoded shared secret.
          example: JBSWY3DPEHPK3PXP
      required:
        - secretKey
    CheckAppointmentBody:
      title: CheckAppointmentBody
      type: object
      additionalProperties: false
      description: |
        The narrow set of `Appointment` fields the check endpoint validates
        against. Unlike the full `UpdateAppointment` body used by `PUT
        /shop/appointments/{appointmentId}`, the check route inspects only
        the practitioner, room and time-of-day slot — the rest of the
        update surface (move, stage, item_configuration, etc.) is not
        consulted by the dry-run.
      properties:
        practitioner_ids:
          type: array
          items:
            type: string
          description: |
            The practitioners that would be assigned to the appointment.
            Each entry must be a valid `Practitioner` ID; the check fails
            if any of the practitioners is unavailable or unqualified for
            the appointment type.
        room_id:
          type: string
          nullable: true
          description: |
            The room the appointment would take place in. Pass `null` to
            check availability without a room constraint.
          example: 5e1e3f6c-2a44-4f6e-8c61-9c1f7d2e1c11
        start_time:
          type: string
          format: time
          description: |
            Time-of-day the appointment would start, in `HH:mm` (24-hour)
            format. The check endpoint validates only the time-of-day slot
            — it does NOT accept a full RFC 3339 datetime; pass the date
            via the path/appointment context and the clock time here.
          example: '14:30'
    VisitIntakeForm:
      title: VisitIntakeForm
      description: |
        A completed visit-intake form — the captured-data record of one
        guest's response to the site's mandatory intake questionnaire,
        tied to a specific basket and order. Used by clinical sites and
        high-touch spas to gather contraindications and consent before a
        visit.
      type: object
      additionalProperties: false
      required:
        - id
        - basket_id
        - customer_id
        - order_ref
        - guest_id
        - type
        - completed_at
      properties:
        id:
          type: string
          description: The ID of the visit intake form.
          example: 634d6e9f413841226003acc2
        basket_id:
          type: string
          description: The ID of the basket the intake form relates to.
          example: 634d6e9f413841226003acc3
        customer_id:
          type: string
          nullable: true
          description: |
            The ID of the customer the intake form was filled out for, if
            the guest is linked to a customer account.
          example: 634d6e9f413841226003acc3
        order_ref:
          type: string
          description: The human-readable reference of the parent order.
          example: TRY123
        guest_id:
          type: string
          description: The ID of the guest the intake form was filled out for.
          example: 634d6e9f413841226003acc4
        type:
          type: string
          nullable: true
          description: |
            The type identifier for the intake form (e.g. `mandatory`,
            `optional`, `treatment-specific`).
          example: mandatory
        completed_at:
          type: string
          format: date-time
          description: When the intake form was filled out.
          example: '2026-11-30T11:52:00+00:00'
        anonymised_at:
          type: string
          format: date-time
          nullable: true
          description: |
            When the captured data was anonymised (typically after the
            retention window has elapsed).
          example: '2027-11-30T11:52:00+00:00'
    SendVoucherPurchaseEmail:
      title: SendVoucherPurchaseEmail
      description: |
        Optional overrides for the recipient details captured at purchase
        time. Pass only the fields you want to change for this send.
      type: object
      additionalProperties: false
      properties:
        recipient_email:
          type: string
          format: email
          description: |
            Override the recipient email address. Defaults to the
            purchase's stored recipient email if omitted.
          example: jane@example.com
        recipient_name:
          type: string
          description: |
            Override the recipient name shown in the email greeting.
            Defaults to the purchase's stored recipient name if omitted.
          example: Jane Jenkins
    VoucherPurchaseEmailAddress:
      title: VoucherPurchaseEmailAddress
      description: A single sender or recipient address.
      type: object
      additionalProperties: false
      required:
        - address
      properties:
        address:
          type: string
          format: email
          description: The email address.
          example: jane@example.com
        name:
          type: string
          nullable: true
          description: The display name accompanying the address, if any.
          example: Jane Jenkins
    VoucherPurchaseMailable:
      title: VoucherPurchaseMailable
      description: |
        A preview-ready representation of a transactional email — sender,
        recipients, subject and rendered HTML body. Returned by
        `previewVoucherPurchaseEmail` and `sendVoucherPurchaseEmail` so
        operator UIs can show the operator exactly what was (or would be)
        delivered.
      type: object
      additionalProperties: false
      required:
        - from
        - to
        - cc
        - bcc
        - subject
        - html
      properties:
        from:
          $ref: '#/components/schemas/VoucherPurchaseEmailAddress'
        to:
          type: array
          description: The `to` recipients.
          items:
            $ref: '#/components/schemas/VoucherPurchaseEmailAddress'
        cc:
          type: array
          description: The `cc` recipients.
          items:
            $ref: '#/components/schemas/VoucherPurchaseEmailAddress'
        bcc:
          type: array
          description: The `bcc` recipients.
          items:
            $ref: '#/components/schemas/VoucherPurchaseEmailAddress'
        subject:
          type: string
          description: The subject line of the email.
          example: Your spa day voucher is here!
        html:
          type: string
          description: The fully-rendered HTML body of the email.
          example: <html><body>Enjoy your day!</body></html>
    YieldInsightsWindow:
      title: YieldInsightsWindow
      description: |
        The concrete datetime window the requested `period` resolved to, or
        `null` when the site has no occupancy history at all to build a
        window from. When the site's data starts too recently to cover the
        whole requested period, `starts_at` reflects where the data
        actually begins rather than the full period.
      type: object
      nullable: true
      additionalProperties: false
      properties:
        starts_at:
          type: string
          format: date-time
          description: When the reporting window starts.
        ends_at:
          type: string
          format: date-time
          description: When the reporting window ends.
      required:
        - starts_at
        - ends_at
    YieldInsightsOpportunities:
      title: YieldInsightsOpportunities
      description: |
        Where the opportunity for demand-based pricing lies — how busy the
        site runs on average, and how many peak and quiet spells its
        occupancy shows over the reporting window.
      type: object
      additionalProperties: false
      properties:
        has_data:
          type: boolean
          description: |
            Whether there is enough occupancy data to calculate the
            opportunity stats. When `false` every stat field in this object
            is `null`; the two threshold fields are always present.
          example: true
        avg_utilisation_percent:
          type: integer
          nullable: true
          description: |
            The site's average utilisation across the reporting window, as
            a whole-number percentage.
          example: 68
        bookable_area_count:
          type: integer
          nullable: true
          description: The number of bookable areas the utilisation is measured across.
          example: 4
        peak_period_count:
          type: integer
          nullable: true
          description: |
            The number of periods in the reporting window where utilisation
            reached `peak_threshold_percent` or above.
          example: 9
        quiet_period_count:
          type: integer
          nullable: true
          description: |
            The number of periods in the reporting window where utilisation
            fell to `quiet_threshold_percent` or below.
          example: 23
        peak_threshold_percent:
          type: integer
          description: |
            The utilisation percentage at or above which a period counts as
            a peak.
          example: 90
        quiet_threshold_percent:
          type: integer
          description: |
            The utilisation percentage at or below which a period counts as
            quiet.
          example: 40
      required:
        - has_data
        - avg_utilisation_percent
        - bookable_area_count
        - peak_period_count
        - quiet_period_count
        - peak_threshold_percent
        - quiet_threshold_percent
    YieldInsightsBookingsByTierEntry:
      title: YieldInsightsBookingsByTierEntry
      description: |
        One reporting tier's share of bookings and revenue over the
        insights window. `standard` is the implicit baseline — bookings
        that sold at standard price because no yield rule applied.
      type: object
      additionalProperties: false
      properties:
        tier:
          type: string
          enum:
            - standard
            - low
            - high
            - peak
          example: low
        count:
          type: integer
          description: The number of bookings in this tier over the reporting window.
          example: 110
        share_percent:
          type: integer
          description: |
            This tier's share of all bookings in the window, as a
            whole-number percentage. Sums to 100 across all tiers.
          example: 22
        revenue:
          type: integer
          description: |
            Total revenue from this tier's bookings, as an integer in the
            minor units of the top-level `currency`.
          example: 1190000
      required:
        - tier
        - count
        - share_percent
        - revenue
    YieldInsightsPerformance:
      title: YieldInsightsPerformance
      description: |
        What yield pricing has earned for the site since it was switched
        on. Monetary amounts are integers in the minor units of the
        top-level `currency` — format them client-side.
      type: object
      additionalProperties: false
      properties:
        has_data:
          type: boolean
          description: |
            Whether there is enough yield activity to calculate the
            performance stats. When `false` every other field in this
            object is `null`.
          example: true
        additional_revenue:
          type: integer
          nullable: true
          description: |
            The extra revenue attributed to yield price adjustments since
            `additional_revenue_since`, as an integer in the minor units of
            the top-level `currency` (e.g. `648000` is £6,480.00 when the
            currency is `GBP`) — not a pre-formatted display string.
          example: 648000
        additional_revenue_since:
          type: string
          format: date
          nullable: true
          description: |
            The date `additional_revenue` accumulates from — when yield
            pricing was switched on for the site.
        aov_uplift_amount:
          type: integer
          nullable: true
          description: |
            How much yield pricing has lifted the site's average order
            value — the uplift itself, not the average order value. An
            integer in the minor units of the top-level `currency` (e.g.
            `1420` is £14.20 when the currency is `GBP`), not a
            pre-formatted display string.
          example: 1420
        aov_uplift_percent:
          type: integer
          nullable: true
          description: |
            The average order value uplift as a whole-number percentage of
            the pre-yield average.
          example: 11
        bookings_at_high_peak_percent:
          type: integer
          nullable: true
          description: |
            The share of bookings taken during high-peak periods, as a
            whole-number percentage.
          example: 36
        bookings_by_tier:
          type: array
          nullable: true
          description: |
            The share of bookings and revenue per reporting tier over the
            window. `null` when `has_data` is `false`.
          items:
            $ref: '#/components/schemas/YieldInsightsBookingsByTierEntry'
      required:
        - has_data
        - additional_revenue
        - additional_revenue_since
        - aov_uplift_amount
        - aov_uplift_percent
        - bookings_at_high_peak_percent
        - bookings_by_tier
    YieldInsights:
      title: YieldInsights
      description: |
        A site-level summary of how yield pricing is set up and performing
        over a recent reporting period. The state flags
        (`has_occupancy_data`, `is_yield_enabled`, `opportunities.has_data`,
        `performance.has_data`) are always present; the stat fields inside
        `opportunities` and `performance` are `null` until the underlying
        calculation has data to work from.
      type: object
      additionalProperties: false
      properties:
        period:
          type: string
          description: The reporting period the insights were calculated over.
          enum:
            - last_30_days
            - last_60_days
            - last_90_days
          example: last_30_days
        window:
          $ref: '#/components/schemas/YieldInsightsWindow'
        currency:
          type: string
          description: |
            The ISO-4217 currency code every monetary amount in this
            response (`performance.additional_revenue`,
            `performance.aov_uplift_amount`) is denominated in. The amounts
            themselves are integers in this currency's minor units.
          example: GBP
        has_occupancy_data:
          type: boolean
          description: |
            Whether the site has any occupancy data at all. When `false`
            there is nothing to calculate insights from, so the stat fields
            elsewhere in the response are `null`.
          example: true
        is_yield_enabled:
          type: boolean
          description: |
            Whether yield pricing is switched on for the site. When `false`
            the `performance` stats have nothing to measure and are `null`.
          example: true
        opportunities:
          $ref: '#/components/schemas/YieldInsightsOpportunities'
        performance:
          $ref: '#/components/schemas/YieldInsightsPerformance'
      required:
        - period
        - window
        - currency
        - has_occupancy_data
        - is_yield_enabled
        - opportunities
        - performance
    YieldInsightsHeatmapDay:
      title: YieldInsightsHeatmapDay
      description: One weekday's hourly fill rates.
      type: object
      additionalProperties: false
      properties:
        day:
          type: string
          enum:
            - mon
            - tue
            - wed
            - thu
            - fri
            - sat
            - sun
          example: mon
        avgs:
          type: object
          description: |
            Fill rate as a whole-number percentage, keyed by the hour's start in the
            site's local time (24-hour `HH:MM`). Only hours the site is open appear.
            A value is `null` where nothing was bookable in that hour.
          additionalProperties:
            type: integer
            minimum: 0
            nullable: true
          example:
            '09:00': 58
            '10:00': 46
            '11:00': null
      required:
        - day
        - avgs
    YieldInsightsHeatmap:
      title: YieldInsightsHeatmap
      description: |
        How full a site's bookable capacity was by weekday and hour over a reporting
        period.

        The three threshold fields band those fill rates for display and are always
        present, whether or not there is any occupancy data. An hour is quiet at or
        below `quiet_threshold_percent`, peak at or above `peak_threshold_percent`,
        high from `high_threshold_percent` up to peak, and standard in between.
      type: object
      additionalProperties: false
      properties:
        period:
          type: string
          enum:
            - last_30_days
            - last_60_days
            - last_90_days
          description: The reporting period the averages cover.
          example: last_30_days
        type:
          type: string
          enum:
            - appointments
            - sessions
          description: Which offerings the averages cover.
          example: appointments
        window:
          $ref: '#/components/schemas/YieldInsightsWindow'
        has_occupancy_data:
          type: boolean
          description: |
            Whether the site has any history to measure. False for a site with no
            completed days of trading, where `heatmap` is empty and the grid has
            nothing to render.
          example: true
        heatmap:
          type: array
          description: |
            One entry per weekday the site is open. Empty until the underlying
            calculation has data to work from.
          items:
            $ref: '#/components/schemas/YieldInsightsHeatmapDay'
        quiet_threshold_percent:
          type: integer
          description: |
            The fill rate at or below which an hour counts as quiet. The same
            threshold the summary endpoint returns, so the grid and the opportunity
            counts band identically.
          example: 40
        high_threshold_percent:
          type: integer
          description: |
            The fill rate at or above which an hour counts as high, up to
            `peak_threshold_percent`. Banding only; nothing is counted against it.
          example: 70
        peak_threshold_percent:
          type: integer
          description: |
            The fill rate at or above which an hour counts as a peak. The same
            threshold the summary endpoint returns.
          example: 90
      required:
        - period
        - type
        - window
        - has_occupancy_data
        - heatmap
        - quiet_threshold_percent
        - high_threshold_percent
        - peak_threshold_percent
    YieldInsightsRevenueComparisonPoint:
      title: YieldInsightsRevenueComparisonPoint
      description: One bucket of the reporting period, with and without yield applied.
      type: object
      additionalProperties: false
      properties:
        date:
          type: string
          format: date
          description: The start of the bucket, on the site's local calendar.
          example: '2026-07-06'
        revenue_with_yield:
          type: integer
          description: |
            What the bucket's bookings actually made, in minor units of the
            top-level `currency`.
          example: 1234000
        revenue_without_yield:
          type: integer
          description: |
            What the same bookings would have made at baseline prices, in minor
            units of the top-level `currency`.
          example: 1180000
      required:
        - date
        - revenue_with_yield
        - revenue_without_yield
    YieldInsightsRevenueComparison:
      title: YieldInsightsRevenueComparison
      description: |
        What the site took over the reporting period against what the same
        bookings would have made at baseline prices.
      type: object
      additionalProperties: false
      properties:
        period:
          type: string
          description: The reporting period the comparison covers.
          enum:
            - last_30_days
            - last_60_days
            - last_90_days
          example: last_30_days
        window:
          $ref: '#/components/schemas/YieldInsightsWindow'
        currency:
          type: string
          description: |
            The ISO-4217 currency code every amount in this response is
            denominated in. The amounts themselves are integers in this
            currency's minor units.
          example: GBP
        has_data:
          type: boolean
          description: |
            Whether there is enough to compare: the site needs both occupancy
            history and yield rules. When `false`, `uplift_percent` is `null`
            and `series` is empty.
          example: true
        uplift_percent:
          type: integer
          nullable: true
          description: |
            How much more the site took over the period than it would have at
            baseline prices, as a whole-number percentage. Negative when
            discounting rules netted below baseline.
          example: 14
        series:
          type: array
          description: |
            The two lines to plot. Empty until the underlying calculation has
            data to work from.
          items:
            $ref: '#/components/schemas/YieldInsightsRevenueComparisonPoint'
      required:
        - period
        - window
        - currency
        - has_data
        - uplift_percent
        - series
    YieldInsightsRoomOccupancyRow:
      title: YieldInsightsRoomOccupancyRow
      description: One bookable resource's hourly fill rates.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          description: The room or bookable area this row measures.
          example: 5f4f1a3b9c9d440000d1f1a1
        name:
          type: string
          example: Treatment Room 1
        kind:
          type: string
          enum:
            - room
            - bookable_area
          description: |
            Which kind of resource the row measures, so a grid can label or group
            rooms separately from bookable areas.
          example: room
        avgs:
          type: object
          description: |
            Fill rate as a whole-number percentage, keyed by the hour's start in the
            site's local time (24-hour `HH:MM`). Only hours the resource was open
            appear. A value is `null` where nothing was bookable in that hour.
          additionalProperties:
            type: integer
            minimum: 0
            nullable: true
          example:
            '09:00': 45
            '11:00': 62
      required:
        - id
        - name
        - kind
        - avgs
    YieldInsightsRoomOccupancy:
      title: YieldInsightsRoomOccupancy
      description: |
        How full each of a site's bookable resources was, by hour, over a reporting
        period.

        Separate from the [demand heatmap](/endpoints/YieldInsights#getYieldInsightsHeatmap)
        because a resource is measured individually rather than pooled into one
        weekday grid: an operator wants to know *which* room is quiet, not just
        when.

        The three threshold fields band those fill rates for display and are always
        present, whether or not there is any occupancy data. They are the same
        thresholds the demand heatmap returns, so the two grids colour identically.
      type: object
      additionalProperties: false
      properties:
        period:
          type: string
          enum:
            - last_30_days
            - last_60_days
            - last_90_days
          description: The reporting period the averages cover.
          example: last_30_days
        window:
          $ref: '#/components/schemas/YieldInsightsWindow'
        has_occupancy_data:
          type: boolean
          description: |
            Whether the site has any history to measure, and any resource to
            measure it against. False where either is missing, and the grid has
            nothing to render.
          example: true
        heatmap:
          type: array
          description: One entry per bookable resource, in the order the site lists them.
          items:
            $ref: '#/components/schemas/YieldInsightsRoomOccupancyRow'
        quiet_threshold_percent:
          type: integer
          description: The fill rate at or below which an hour counts as quiet.
          example: 40
        high_threshold_percent:
          type: integer
          description: |
            The fill rate at or above which an hour counts as high, up to
            `peak_threshold_percent`. Banding only; nothing is counted against it.
          example: 70
        peak_threshold_percent:
          type: integer
          description: The fill rate at or above which an hour counts as a peak.
          example: 90
      required:
        - period
        - window
        - has_occupancy_data
        - heatmap
        - quiet_threshold_percent
        - high_threshold_percent
        - peak_threshold_percent
    weekday:
      type: string
      description: A day of the week, lower case.
      enum:
        - monday
        - tuesday
        - wednesday
        - thursday
        - friday
        - saturday
        - sunday
    UtilisationBand:
      title: UtilisationBand
      description: |
        A percentage band a demand measurement is tested against.

        The band is half-open: `from` is inclusive and `to` is exclusive, so
        consecutive bands can share a boundary without both matching it. Given
        `0–30` and `30–60`, a measurement of exactly 30 matches only the second.

        A `to` of 100 is the exception and is inclusive, so a top band of `60–100`
        matches a fully utilised site rather than leaving 100 uncovered.

        "Only when completely full" is expressed by leaving `to` unset, which is
        unbounded upwards, rather than by `100`–`100`.

        Because the upper bound is exclusive, bounds that meet describe nothing and
        are rejected — `30`–`30` would never apply.

        An absent bound is unbounded in that direction. Both bounds `null` means the
        band is not set.
      type: object
      additionalProperties: false
      properties:
        from:
          type: integer
          minimum: 0
          maximum: 100
          nullable: true
          description: Lowest percentage this band matches, inclusive.
          example: 70
        to:
          type: integer
          minimum: 0
          maximum: 100
          nullable: true
          description: |
            Upper bound of the band, exclusive — unless it is 100, which is
            inclusive. Must be greater than or equal to `from` when both are set.
          example: 90
      required:
        - from
        - to
    YieldRuleTriggers:
      title: YieldRuleTriggers
      description: |
        The demand conditions under which a rule fires.

        At least one band must be set. When both are set the rule fires if either
        is satisfied, so setting both widens a rule rather than narrowing it.
      type: object
      additionalProperties: false
      properties:
        practitioner_utilisation:
          $ref: '#/components/schemas/UtilisationBand'
        room_occupancy:
          $ref: '#/components/schemas/UtilisationBand'
      required:
        - practitioner_utilisation
        - room_occupancy
    yieldRounding:
      type: string
      nullable: true
      description: |
        Rounds the adjusted price to the nearest whole unit of currency. `null`
        leaves the adjusted price unrounded.
      enum:
        - one
        - five
        - ten
    YieldRule:
      title: YieldRule
      description: |
        A demand-based price adjustment configured for a single offering.

        Adjustments apply on top of the offering's existing price rules, and are
        bounded by its yield price guardrails. Rules are per-offering: applying one
        to several offerings at once creates an independent rule for each, so
        editing one never affects the others.
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
        offering_type:
          $ref: '#/components/schemas/offeringType'
        offering_id:
          type: string
          format: uuid
          description: The offering this rule adjusts the price of.
        site_id:
          type: string
          format: uuid
        created_batch_id:
          type: string
          format: uuid
          nullable: true
          description: |
            Shared by every rule created in the same request. The rules remain
            independent of one another — editing one does not affect the others — so
            this only records that they were created together.
        weekdays:
          type: array
          description: The days of the week this rule applies on.
          items:
            $ref: '#/components/schemas/weekday'
        time_from:
          type: string
          nullable: true
          description: |
            Start of the daily window this rule applies within, in the site's local
            time. 24-hour `HH:MM`. Each selected weekday is the day its window
            starts on. Null alongside a null `time_to` means the rule applies all
            day.
          example: '12:00'
        time_to:
          type: string
          nullable: true
          description: |
            End of the daily window this rule applies within, in the site's local
            time. 24-hour `HH:MM`. A value earlier than `time_from` means the window
            runs past midnight into the following day. Null alongside a null
            `time_from` means the rule applies all day.
          example: '21:00'
        triggers:
          $ref: '#/components/schemas/YieldRuleTriggers'
        adjustment:
          $ref: '#/components/schemas/YieldRuleAdjustment'
        rounding:
          $ref: '#/components/schemas/yieldRounding'
        reporting_tier:
          $ref: '#/components/schemas/yieldReportingTier'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
          description: |
            When several rules could apply to the same slot, the most recently
            updated one wins.
      required:
        - id
        - offering_type
        - offering_id
        - site_id
        - created_batch_id
        - weekdays
        - time_from
        - time_to
        - triggers
        - adjustment
        - rounding
        - reporting_tier
        - created_at
        - updated_at
    YieldRuleOfferingIdentifier:
      title: YieldRuleOfferingIdentifier
      description: |
        Identifies an offering to apply a rule to. The type is required alongside
        the ID because an ID alone does not identify which kind of offering it is.
      type: object
      additionalProperties: false
      properties:
        offering_type:
          $ref: '#/components/schemas/offeringType'
        offering_id:
          type: string
          format: uuid
      required:
        - offering_type
        - offering_id
    TokenInfo:
      title: TokenInfo
      description: |
        Standard JWT claims decoded from the caller's bearer token.
        All timestamps are seconds since the Unix epoch (i.e.
        standard JWT NumericDate). Custom or private claims are not
        included.
      type: object
      additionalProperties: false
      properties:
        aud:
          type: string
          description: |
            The audience claim — the OAuth client ID the token was
            issued to.
        jti:
          type: string
          description: |
            Unique identifier for this specific token, mirroring the
            record in Trybe's access-token store.
        iat:
          type: integer
          format: int64
          description: |
            Issued-at timestamp, in seconds since the Unix epoch.
        nbf:
          type: integer
          format: int64
          description: |
            Not-before timestamp, in seconds since the Unix epoch.
            The token is not valid before this instant.
        exp:
          type: integer
          format: int64
          description: |
            Expiry timestamp, in seconds since the Unix epoch. The
            token cannot be used to authenticate after this instant.
        sub:
          type: string
          description: |
            Subject — the ID of the user (or API user) the token is
            bound to.
    NewMembershipRate:
      title: NewMembershipRate
      type: object
      additionalProperties: false
      description: |
        A publicly bookable membership rate, with the pricing breakdown a
        storefront needs to render a "join now" CTA: recurring fee,
        joining fee and the calculated pro-rata for an immediate signup.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the membership rate.
        name:
          type: string
          description: The display name of the rate.
          example: Standard rate
        currency:
          type: string
          description: |
            The ISO-4217 currency code (uppercase) that all monetary
            fields on this rate are denominated in.
          example: GBP
        price:
          type: integer
          description: |
            The recurring price charged every billing period, expressed
            as an integer of the smallest currency unit (e.g. pence).
          example: 3000
        joining_fee:
          type: integer
          description: |
            A one-off joining fee taken at signup, expressed as an
            integer of the smallest currency unit. Zero if no joining
            fee applies.
          example: 1000
        billing_frequency:
          type: string
          description: |
            The cadence at which the recurring fee is charged, expressed
            as an ISO-8601 duration (for example `P1M` for monthly,
            `P1Y` for annually).
          example: P1M
        notice_period:
          type: string
          nullable: true
          enum:
            - P7D
            - P14D
            - P1M
            - P3M
            - P6M
            - P1Y
            - null
          description: |
            How much notice a customer must give to cancel a membership on
            this rate, expressed as an ISO-8601 duration. Null when no
            notice is required.
          example: P1M
        pro_rata:
          type: integer
          description: |
            The pro-rata charge owed for the partial billing period
            between today and the next billing-cycle boundary, expressed
            as an integer of the smallest currency unit. Zero when the
            signup happens to align with the start of a billing cycle.
          example: 1500
      required:
        - id
        - name
        - currency
        - price
        - joining_fee
        - billing_frequency
        - notice_period
        - pro_rata
    NewMembershipType:
      title: NewMembershipType
      type: object
      additionalProperties: false
      description: |
        A membership type as it appears on the public new-membership
        signup form, with its publicly bookable rates.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the membership type.
        name:
          type: string
          description: The display name of the membership type.
          example: Gold tier
        rates:
          type: array
          description: |
            The publicly bookable rates for this type. If a
            `MembershipSignupToken` was supplied that pins a single rate,
            this array contains only that rate.
          items:
            $ref: '#/components/schemas/NewMembershipRate'
      required:
        - id
        - name
        - rates
    schemas_MembershipTypeSummary-2:
      title: MembershipTypeSummary
      type: object
      additionalProperties: false
      description: |
        The minimal `{ id, name }` projection of a `MembershipType` used
        by the ordered-membership-types endpoints. For the full payload
        (with rates, visibility, etc.) see the [`MembershipType`](#schema/MembershipType)
        schema.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the membership type.
        name:
          type: string
          description: The display name of the membership type.
          example: Gold tier
      required:
        - id
        - name
    PublicMarketingPreference:
      title: PublicMarketingPreference
      type: object
      additionalProperties: false
      description: |
        The public-safe projection of a marketing preference — just the
        ID (so the signup form can post the selected IDs back) and the
        display text to render to the guest. Crucially, this does **not**
        include the owning `organisation_id`, since the caller already
        supplied it as the filter.
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the marketing preference.
        text:
          type: string
          description: The text to display next to the consent checkbox.
          example: I want to receive emails about special offers
      required:
        - id
        - text
    CustomerSegment:
      type: object
      title: CustomerSegment
      additionalProperties: false
      description: A named group of customers within a site that can be targeted for marketing campaigns. Segments can be defined manually or filtered automatically by label and membership criteria.
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the customer segment.
        name:
          type: string
          description: The display name of the segment.
          example: Premium Members
        site_id:
          type: string
          format: uuid
          description: The ID of the site this segment belongs to.
        filters:
          type: object
          title: CustomerSegmentFilters
          description: Optional filters that define automatic membership criteria for this segment. `null` indicates no filters are applied.
          nullable: true
          additionalProperties: false
          properties:
            all_customers:
              type: boolean
              description: When `true`, all customers in the site are included in the segment regardless of other filters.
            label_ids:
              type: array
              description: Customers that have all of the given label IDs are included in the segment.
              nullable: true
              items:
                type: string
                format: uuid
                description: The ID of a label.
            membership_type_ids:
              description: Customers that hold a membership matching one of the given IDs are included in the segment. Use `true` to include customers with any active membership.
              oneOf:
                - type: array
                  nullable: true
                  items:
                    type: string
                    format: uuid
                    description: The ID of a membership.
                - type: boolean
                  enum:
                    - true
      required:
        - id
        - name
        - site_id
        - filters
    CustomerSegmentMember:
      type: object
      title: CustomerSegmentMember
      additionalProperties: false
      description: A customer who is a member of a `CustomerSegment`. Tracks subscription state for marketing communications.
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the segment membership record.
        segment_id:
          type: string
          format: uuid
          description: The ID of the segment this membership belongs to.
        unsubscribed_at:
          type: string
          format: date-time
          description: The datetime at which the customer unsubscribed from this segment's communications, or `null` if they are currently subscribed.
          nullable: true
        customer:
          $ref: '#/components/schemas/CustomerSummary'
      required:
        - id
        - segment_id
        - unsubscribed_at
        - customer
    Campaign:
      type: object
      title: Campaign
      additionalProperties: false
      description: An email marketing campaign sent to the members of a `CustomerSegment`. A campaign can be scheduled in advance and tracks when it was sent.
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the campaign.
        name:
          type: string
          description: The display name of the campaign.
          example: Summer Promotion 2024
        progress:
          type: number
          format: float
          description: |
            The send progress of the campaign as a percentage (0–100). Only populated
            when `status` is `in_progress`; `null` otherwise.
          nullable: true
          minimum: 0
          maximum: 100
          example: 42.5
        scheduled_at:
          type: string
          format: date-time
          description: The datetime at which this campaign is scheduled to be sent, or `null` if not yet scheduled.
          nullable: true
        segment:
          type: object
          title: CampaignSegmentSummary
          additionalProperties: false
          description: A summary of the `CustomerSegment` this campaign is targeting, or `null` if no segment has been assigned.
          nullable: true
          properties:
            id:
              type: string
              format: uuid
              description: The ID of the segment.
            name:
              type: string
              description: The display name of the segment.
              example: Premium Members
          required:
            - id
            - name
        sent_at:
          type: string
          format: date-time
          description: The datetime at which this campaign was sent, or `null` if it has not yet been sent.
          nullable: true
        site_id:
          type: string
          format: uuid
        status:
          type: string
          description: |
            The current send status of the campaign.
            - `unsent` — no send records exist yet.
            - `in_progress` — sends have been created but at least one has not yet been sent.
            - `sent` — all send records have been sent.
          enum:
            - unsent
            - in_progress
            - sent
          example: unsent
      required:
        - id
        - name
        - progress
        - scheduled_at
        - segment
        - sent_at
        - site_id
        - status
    CampaignContent:
      type: object
      title: CampaignContent
      additionalProperties: false
      description: The localised content (subject line and body) for a `Campaign`. A campaign may have multiple content records — one per locale — enabling multi-language sends.
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the campaign content.
        campaign_id:
          type: string
          format: uuid
          description: The unique identifier of the campaign.
        locale:
          type: string
          description: The BCP 47 locale code for this content variant.
          example: en-GB
        subject:
          type: string
          nullable: true
          description: The email subject line for this content variant.
          example: Exclusive summer offer just for you 🌞
        content:
          type: string
          nullable: true
          description: The email body content for this content variant. May contain HTML.
          example: <p>Hi there! We have a special offer just for you.</p>
      required:
        - id
        - campaign_id
        - locale
        - subject
        - content
    CampaignSend:
      type: object
      title: CampaignSend
      additionalProperties: false
      description: A record of a single email send to one member of a `Campaign`. Tracks delivery lifecycle events — sent, failed, bounced, opened, and clicked.
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier of the campaign send.
        campaign_id:
          type: string
          format: uuid
          description: The ID of the campaign this send belongs to.
        campaign_content_id:
          type: string
          format: uuid
          description: The ID of the `CampaignContent` used for this send.
        member_id:
          type: string
          format: uuid
          description: The ID of the `CustomerSegmentMember` this send was addressed to.
        subject:
          type: string
          description: The email subject line used for this send.
          example: Exclusive summer offer just for you
        sent_at:
          type: string
          format: date-time
          description: The datetime at which the email was sent, or `null` if not yet sent.
          nullable: true
        failed_at:
          type: string
          format: date-time
          description: The datetime at which the send failed, or `null` if it has not failed.
          nullable: true
        bounced_at:
          type: string
          format: date-time
          description: The datetime at which the email bounced, or `null` if it has not bounced.
          nullable: true
        clicked_at:
          type: string
          format: date-time
          description: The datetime at which the recipient first clicked a link in the email, or `null` if no click has been recorded.
          nullable: true
        opened_at:
          type: string
          format: date-time
          description: The datetime at which the recipient first opened the email, or `null` if no open has been recorded.
          nullable: true
        customer:
          type: object
          title: CampaignSendCustomer
          additionalProperties: false
          description: Summary of the customer this email was sent to.
          nullable: true
          properties:
            id:
              type: string
              format: uuid
              description: The ID of the customer.
            first_name:
              type: string
              description: The first name of the customer.
              example: Jane
            last_name:
              type: string
              description: The last name of the customer.
              example: Doe
            email:
              type: string
              format: email
              description: The email address of the customer.
              example: janedoe@example.com
          required:
            - id
            - first_name
            - last_name
            - email
      required:
        - id
        - campaign_id
        - campaign_content_id
        - member_id
        - subject
        - sent_at
        - failed_at
        - bounced_at
        - clicked_at
        - opened_at
        - customer
  responses:
    ListApiUsers:
      description: A list of API users
      content:
        application/json:
          schema:
            title: ListApiUsers
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListApiUsersData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ApiUser'
    Unauthenticated:
      description: The user is unauthenticated
      content:
        application/json:
          schema:
            title: Unauthenticated
            type: object
            additionalProperties: false
            required:
              - message
            properties:
              message:
                type: string
                example: Unauthenticated
    ShowApiUserWithToken:
      description: |
        A newly created API user, including the access token. The
        `token` field is only returned on the create response — it is
        not persisted by Trybe in a retrievable form, so store it
        securely as soon as you receive it.
      content:
        application/json:
          schema:
            title: ShowApiUserWithToken
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowApiUserWithTokenData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/ApiUserWithToken'
    Forbidden:
      description: The authenticated user does not have permission.
      content:
        application/json:
          schema:
            title: Forbidden
            type: object
            additionalProperties: false
            required:
              - message
            properties:
              message:
                type: string
                example: This action is unauthorized.
    ValidationFailed:
      description: The request didn't pass validation
      content:
        application/json:
          schema:
            title: ValidationFailed
            type: object
            additionalProperties: false
            required:
              - errors
              - message
            properties:
              errors:
                type: object
                description: A list of validation errors.
                additionalProperties:
                  type: array
                  items:
                    type: string
                    description: The validation error message.
              message:
                type: string
                description: A description of the error
                example: The request didn't pass validation
    ShowApiUser:
      description: An API User
      content:
        application/json:
          schema:
            title: ShowApiUser
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowApiUserData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/ApiUser'
    EntityNotFound:
      description: The resource couldn't be found
      content:
        application/json:
          schema:
            title: EntityNotFound
            additionalProperties: false
            type: object
            properties:
              message:
                type: string
                description: A description of the error
                example: The requested resource could not be found
    ListSupportedLocales:
      description: A list of the platform's supported locales
      content:
        application/json:
          schema:
            title: ListSupportedLocales
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListSupportedLocalesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SupportedLocale'
                    example:
                      - code: en
                        name: English
                        emoji: 🇬🇧
                      - code: fr
                        name: Français
                        emoji: 🇫🇷
    ListSupportedCurrencies:
      description: A list of the platform's supported currencies
      content:
        application/json:
          schema:
            title: ListSupportedCurrencies
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListSupportedCurrenciesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SupportedCurrency'
                    example:
                      - code: GBP
                      - code: EUR
    ListSupportedTimezones:
      description: A list of the platform's supported timezones
      content:
        application/json:
          schema:
            title: ListSupportedTimezones
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListSupportedTimezonesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SupportedTimezone'
                    example:
                      - code: Europe/Paris
                      - code: Atlantic/Faroe
    ListOutboundIps:
      description: A list of the platform's outbound IP addresses for the current environment
      content:
        application/json:
          schema:
            title: ListOutboundIps
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListOutboundIpsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/OutboundIp'
                    example:
                      - 63.34.76.240
                      - 34.253.58.14
    ShowSite:
      description: The `Site` was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowSite
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Site'
            required:
              - data
    ShowSiteLogo:
      description: The `Site`'s logo was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowSiteLogo
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Media'
                nullable: true
            required:
              - data
    ListCalendarNotes:
      description: A paginated list of `CalendarNote` objects for the site.
      content:
        application/json:
          schema:
            title: ListCalendarNotes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The calendar notes on this page.
                items:
                  $ref: '#/components/schemas/CalendarNote'
            required:
              - data
    ShowCalendarNote:
      description: A single `CalendarNote`.
      content:
        application/json:
          schema:
            title: ShowCalendarNote
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CalendarNote'
            required:
              - data
    BadRequest:
      description: The request failed.
      content:
        application/json:
          schema:
            title: BadRequest
            additionalProperties: false
            type: object
            properties:
              message:
                type: string
                description: A description of the error
    ShowTerminalRequest:
      description: The Terminal Request was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowTerminalRequest
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/TerminalRequest'
            required:
              - data
    ShowCardTokenisationRequest:
      description: The Card Tokenisation was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowCardTokenisationRequest
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CardTokenisationRequest'
            required:
              - data
    ListAppointmentTypes:
      description: A paginated list of `AppointmentType`s for the requested site.
      content:
        application/json:
          schema:
            title: ListAppointmentTypes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The appointment types on this page, ordered by name.
                items:
                  $ref: '#/components/schemas/AppointmentType'
            required:
              - data
    ShowAppointmentType:
      description: A single `AppointmentType`.
      content:
        application/json:
          schema:
            title: ShowAppointmentType
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AppointmentType'
            required:
              - data
    ListAppointmentTypeAvailabilityRules:
      description: A list of `AvailabilityRule`s on an `AppointmentType`.
      content:
        application/json:
          schema:
            title: ListAppointmentTypeAvailabilityRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The availability rules configured for this appointment type. Order is not guaranteed.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ShowAppointmentTypeAvailabilityRule:
      description: A single `AvailabilityRule`.
      content:
        application/json:
          schema:
            title: ShowAppointmentTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ListAppointmentTypePriceRules:
      description: A list of price rules for an appointment type.
      content:
        application/json:
          schema:
            title: ListAppointmentTypePriceRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_PriceRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              total:
                type: integer
                description: The total number of price rules for this appointment type without filters applied.
            required:
              - data
              - meta
              - total
    ShowAppointmentTypePriceRule:
      description: A single `PriceRule` on an `AppointmentType`.
      content:
        application/json:
          schema:
            title: ShowAppointmentTypePriceRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PriceRule'
            required:
              - data
    ShowAppointmentTypeLocaleStrings:
      description: The locale strings for the appointment type were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowAppointmentTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    UpdateAppointmentTypeLocaleStrings:
      description: The locale strings for the appointment type were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateAppointmentTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    ListAreaBookingTypes:
      description: A paginated list of `AreaBookingType`s for the requested site.
      content:
        application/json:
          schema:
            title: ListAreaBookingTypes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The area booking types on this page, ordered by name.
                items:
                  $ref: '#/components/schemas/AreaBookingType'
            required:
              - data
    ShowAreaBookingType:
      description: A single `AreaBookingType`.
      content:
        application/json:
          schema:
            title: ShowAreaBookingType
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AreaBookingType'
            required:
              - data
    ListAreaBookingTypeAvailabilityRules:
      description: A list of `AvailabilityRule`s on an `AreaBookingType`.
      content:
        application/json:
          schema:
            title: ListAreaBookingTypeAvailabilityRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The availability rules configured for this area booking type. Order is not guaranteed.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ShowAreaBookingTypeAvailabilityRule:
      description: A single `AvailabilityRule`.
      content:
        application/json:
          schema:
            title: ShowAreaBookingTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ListAreaBookingTypePriceRules:
      description: A paginated list of price rules for an area booking type.
      content:
        application/json:
          schema:
            title: ListAreaBookingTypePriceRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_PriceRule-2'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              total:
                type: integer
                description: The total number of price rules for this area booking type without filters applied.
            required:
              - data
              - meta
              - total
    ShowAreaBookingTypePriceRule:
      description: A single price rule on an `AreaBookingType`.
      content:
        application/json:
          schema:
            title: ShowAreaBookingTypePriceRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PriceRule-2'
            required:
              - data
    ShowAreaBookingTypeLocaleStrings:
      description: The locale strings for the area booking type were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowAreaBookingTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    UpdateAreaBookingTypeLocaleStrings:
      description: The locale strings for the area booking type were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateAreaBookingTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    ShowIntakeFormLink:
      description: A response containing the link to the intake form
      content:
        application/json:
          schema:
            title: ShowIntakeFormLink
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/IntakeFormLink'
    ListBookableAreas:
      description: A paginated list of `BookableArea`s.
      content:
        application/json:
          schema:
            title: ListBookableAreas
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The bookable areas on this page, ordered by `order` then by name.
                items:
                  $ref: '#/components/schemas/BookableArea'
            required:
              - data
    ShowBookableArea:
      description: A single `BookableArea`.
      content:
        application/json:
          schema:
            title: ShowBookableArea
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/BookableArea'
            required:
              - data
    ListOrderedBookableAreas:
      description: |
        The site's bookable areas in display order. Pair with
        `PUT /shop/bookable-areas/order` to power a drag-and-drop UI.
      content:
        application/json:
          schema:
            title: ListOrderedBookableAreas
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The bookable areas in their current display order.
                items:
                  $ref: '#/components/schemas/BookableAreaSummary'
            required:
              - data
    ListBookableAreaAvailabilityRules:
      description: A list of `AvailabilityRule`s on a `BookableArea`.
      content:
        application/json:
          schema:
            title: ListBookableAreaAvailabilityRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The availability rules configured for this bookable area. Order is not guaranteed.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ShowBookableAreaAvailabilityRule:
      description: A single `AvailabilityRule`.
      content:
        application/json:
          schema:
            title: ShowBookableAreaAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ShowCourseTypeEnvelope:
      description: A single `CourseType`.
      content:
        application/json:
          schema:
            title: ShowCourseTypeEnvelope
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/CourseType'
    ShowCourseTypeLocaleStrings:
      description: The locale strings for the course type were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCourseTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    UpdateCourseTypeLocaleStrings:
      description: The locale strings for the course type were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateCourseTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    ListCourseTypeAvailabilityRules:
      description: A list of `AvailabilityRule`s on a `CourseType`.
      content:
        application/json:
          schema:
            title: ListCourseTypeAvailabilityRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The availability rules configured for this course type. Order is not guaranteed.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ShowCourseTypeAvailabilityRule:
      description: A single `AvailabilityRule` on a `CourseType`.
      content:
        application/json:
          schema:
            title: ShowCourseTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ListCourseTypePriceRules:
      description: A list of price rules for a course type.
      content:
        application/json:
          schema:
            title: ListCourseTypePriceRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The price rules configured for this course type, filtered by any date-range query parameters.
                items:
                  $ref: '#/components/schemas/schemas_PriceRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              total:
                type: integer
                description: Total number of price rules on this course type without filters applied.
                example: 3
            required:
              - data
              - meta
              - total
    ShowCourseTypePriceRule:
      description: A single `PriceRule` on a `CourseType`.
      content:
        application/json:
          schema:
            title: ShowCourseTypePriceRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PriceRule'
            required:
              - data
    CustomerSearchResponse:
      description: Contains the customer stats.
      content:
        application/json:
          schema:
            type: object
            title: CustomerSearchResponse
            additionalProperties: false
            properties:
              data:
                type: array
                description: The list of customers matching the search criteria.
                items:
                  $ref: '#/components/schemas/CustomerSearchResult'
              meta:
                $ref: '#/components/schemas/CustomerSearchMeta'
            required:
              - data
              - meta
    CustomerStatsResponse:
      description: Contains the customer stats.
      content:
        application/json:
          schema:
            type: object
            title: ShowDiscountType
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerStats'
              meta:
                $ref: '#/components/schemas/CustomerStatsMeta'
            required:
              - data
              - meta
    ListEquipment:
      description: A paginated list of `Equipment` items configured at the site.
      content:
        application/json:
          schema:
            title: ListEquipment
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The equipment items on this page.
                items:
                  $ref: '#/components/schemas/Equipment'
            required:
              - data
    ShowEquipment:
      description: A single `Equipment` item.
      content:
        application/json:
          schema:
            title: ShowEquipment
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Equipment'
            required:
              - data
    ListDiscountTypes:
      description: The Discount Types were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListDiscountTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/DiscountType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowDiscountType:
      description: The Discount Type was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowDiscountType
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/DiscountType'
            required:
              - data
    ListOrderedDiscountTypes:
      description: The ordered Discount Types were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListOrderedDiscountTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/DiscountTypeSummary'
            required:
              - data
    ListExternalIdTypes:
      description: The external ID types were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListExternalIdTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/ExternalIdType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowExternalIdType:
      description: The external ID type was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowExternalIdType
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/ExternalIdType'
            required:
              - data
    ListHotelRoomTypesResponse:
      description: Contains an array of hotel room types.
      content:
        application/json:
          schema:
            type: object
            title: ListHotelRoomTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/HotelRoomType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    HotelRoomTypeResponse:
      description: Contains details of a single table reservation type.
      content:
        application/json:
          schema:
            type: object
            title: HotelRoomTypeResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/HotelRoomType'
            required:
              - data
    AppointmentEnquiryAvailabilityResponse:
      description: Results of the availability check for an appointment enquiry
      content:
        application/json:
          schema:
            title: AppointmentEnquiryAvailabilityResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AppointmentEnquiryAvailabilityResult'
            required:
              - data
    TableReservationSlots:
      description: The table reservation slots were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: TableReservationSlots
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/TableReservationSlot'
            required:
              - data
    OrderableIntakeFormSections:
      description: Successfully retrieved orderable `IntakeFormSection`s.
      content:
        application/json:
          schema:
            title: ListOrderableIntakeFormSectionsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderableIntakeFormSection'
            required:
              - data
    ListPackages:
      description: A paginated list of `Package`s for the requested site.
      content:
        application/json:
          schema:
            title: ListPackages
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListPackagesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: The packages on this page, ordered by name.
                    items:
                      $ref: '#/components/schemas/schemas_Package'
    ShowPackage:
      description: A single `Package`.
      content:
        application/json:
          schema:
            title: ShowPackage
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowPackageData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Package'
    ShowPackageLocaleStrings:
      description: The locale strings for the package were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowPackageLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    UpdatePackageLocaleStrings:
      description: The locale strings for the package were successfully updated.
      content:
        application/json:
          schema:
            title: UpdatePackageLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    ShowPackageItemChoiceLocaleStrings:
      description: The locale strings for the package item choice were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowPackageItemChoiceLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingBasicLocaleStrings'
            required:
              - data
    UpdatePackageItemChoiceLocaleStrings:
      description: The locale strings for the package item choice were successfully updated.
      content:
        application/json:
          schema:
            title: UpdatePackageItemChoiceLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingBasicLocaleStrings'
            required:
              - data
    ListProductsResponse:
      description: |
        A list of product response objects.
      content:
        application/json:
          schema:
            title: ListProductsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_Product'
            required:
              - data
    ProductResponse:
      description: |
        A product response object.
      content:
        application/json:
          schema:
            title: ProductResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_Product'
            required:
              - data
    ListProductPriceRules:
      description: A list of price rules for a product.
      content:
        application/json:
          schema:
            title: ListProductPriceRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The price rules configured for this product, filtered by any date range query parameters.
                items:
                  $ref: '#/components/schemas/schemas_PriceRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              total:
                type: integer
                description: The total number of price rules for this product without filters applied.
                example: 5
            required:
              - data
              - meta
              - total
    ShowProductPriceRule:
      description: A single `PriceRule` on a `Product`.
      content:
        application/json:
          schema:
            title: ShowProductPriceRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PriceRule'
            required:
              - data
    SuggestedDescription:
      description: A suggested description
      content:
        application/json:
          schema:
            title: SuggestedDescription
            type: object
            additionalProperties: false
            properties:
              data:
                type: object
                additionalProperties: false
                title: SuggestedDescriptionData
                properties:
                  description:
                    type: string
                    description: A suggested description generated by Trybe Intelligence.
                required:
                  - description
            required:
              - data
    ShowProductLocaleStrings:
      description: The locale strings for the product were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowProductLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingBasicLocaleStrings'
            required:
              - data
    UpdateProductLocaleStrings:
      description: The locale strings for the product were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateProductLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingBasicLocaleStrings'
            required:
              - data
    ListRooms:
      description: A paginated list of `Room`s.
      content:
        application/json:
          schema:
            title: ListRooms
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListRoomsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: |
                      The rooms on this page, ordered by `order` then by name.
                    items:
                      $ref: '#/components/schemas/Room'
    ShowRoom:
      description: A single `Room`.
      content:
        application/json:
          schema:
            title: ShowRoom
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowRoomData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Room'
    ListOrderedRooms:
      description: |
        The site's rooms in display order. Used to drive a drag-and-drop
        ordering UI alongside the matching `PUT /shop/rooms/order` endpoint.
      content:
        application/json:
          schema:
            title: ListOrderedRooms
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListOrderedRoomsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: The rooms in their current display order.
                    items:
                      $ref: '#/components/schemas/RoomSummary'
    QueuedJobResponse:
      description: The job was successfully queued
      content:
        application/json:
          schema:
            title: QueuedJobResponse
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/QueuedJob'
    ListTableReservationTypeResponse:
      description: Contains an array of table reservation types.
      content:
        application/json:
          schema:
            type: object
            title: ListTableReservationTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/TableReservationType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    TableReservationTypeResponse:
      description: Contains details of a single table reservation type.
      content:
        application/json:
          schema:
            type: object
            title: TableReservationTypeResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/TableReservationType'
            required:
              - data
    TableReservationOptionResponse:
      description: Contains details of a single table reservation option.
      content:
        application/json:
          schema:
            type: object
            title: TableReservationTypeResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_TableReservationOption'
            required:
              - data
    ListAllPractitionerRotas:
      description: A paginated list of `PractitionerRota` objects across all practitioners the caller can see.
      content:
        application/json:
          schema:
            title: ListAllPractitionerRotas
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/PractitionerRota'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowPractitionerRotaById:
      description: A single `PractitionerRota` object.
      content:
        application/json:
          schema:
            title: ShowPractitionerRotaById
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/PractitionerRota'
            required:
              - data
    ListPractitionerTags:
      description: A paginated list of `PractitionerTag` objects.
      content:
        application/json:
          schema:
            title: ListPractitionerTags
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListPractitionerTagsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: The practitioner tags on this page.
                    items:
                      $ref: '#/components/schemas/PractitionerTag'
    ShowPractitionerTag:
      description: A single `PractitionerTag`.
      content:
        application/json:
          schema:
            title: ShowPractitionerTag
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowPractitionerTagData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/PractitionerTag'
    ListPractitioners:
      description: A list of practitioners (paginated)
      content:
        application/json:
          schema:
            title: ListPractitioners
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListPractitionersData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Practitioner'
    ListPractitionerAppointmentRestrictions:
      description: A paginated list of `PractitionerAppointmentRestriction` objects belonging to the practitioner.
      content:
        application/json:
          schema:
            title: ListPractitionerAppointmentRestrictions
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The restrictions configured for this practitioner. Order is not guaranteed.
                items:
                  $ref: '#/components/schemas/schemas_PractitionerAppointmentRestriction'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowPractitionerAppointmentRestriction:
      description: A single `PractitionerAppointmentRestriction`.
      content:
        application/json:
          schema:
            title: ShowPractitionerAppointmentRestriction
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PractitionerAppointmentRestriction'
            required:
              - data
    ListPractitionerCustomAvailability:
      description: A paginated list of `PractitionerCustomAvailability` rules for the practitioner.
      content:
        application/json:
          schema:
            title: ListPractitionerCustomAvailability
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The custom availability rules covering the filtered range. Order is by `date_time_from` ascending.
                items:
                  $ref: '#/components/schemas/PractitionerCustomAvailability'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowPractitionerCustomAvailability:
      description: A single `PractitionerCustomAvailability` rule.
      content:
        application/json:
          schema:
            title: ShowPractitionerCustomAvailability
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/PractitionerCustomAvailability'
            required:
              - data
    ListPractitionerRotasResponse:
      description: A paginated list of `PractitionerRota` objects.
      content:
        application/json:
          schema:
            title: ListPractitionerRotasResponse
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/PractitionerRota'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowPractitionerRotaResponse:
      description: A single `PractitionerRota` object.
      content:
        application/json:
          schema:
            title: ShowPractitionerRotaResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/PractitionerRota'
            required:
              - data
    ListRoomTags:
      description: A paginated list of `RoomTag` objects.
      content:
        application/json:
          schema:
            title: ListRoomTags
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The room tags on this page.
                items:
                  $ref: '#/components/schemas/RoomTag'
            required:
              - data
    ShowRoomTag:
      description: A single `RoomTag`.
      content:
        application/json:
          schema:
            title: ShowRoomTag
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/RoomTag'
            required:
              - data
    ListZones:
      description: A paginated list of `Zone` objects configured at the site.
      content:
        application/json:
          schema:
            title: ListZones
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: |
                  The zones on this page, in arbitrary order. Page with
                  `page` + `per_page` query parameters to walk the full
                  set.
                items:
                  $ref: '#/components/schemas/Zone'
            required:
              - data
    ShowZone:
      description: A single `Zone`.
      content:
        application/json:
          schema:
            title: ShowZone
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Zone'
            required:
              - data
    ListTaxConfigurations:
      description: A list of tax configurations.
      content:
        application/json:
          schema:
            type: object
            title: ListTaxConfigurations
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/TaxConfiguration'
            required:
              - data
    ShowTaxConfiguration:
      description: A single tax configuration.
      content:
        application/json:
          schema:
            type: object
            title: ShowTaxConfiguration
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/TaxConfiguration'
            required:
              - data
    TestTaxConfiguration:
      description: The results of a tax calculation for a tax configuration.
      content:
        application/json:
          schema:
            type: object
            title: ListRevenueCentres
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/TaxCalculation'
            required:
              - data
    ListVisitTypesResponse:
      description: The response to a request to list `VisitType`s
      content:
        application/json:
          schema:
            title: ListVisitTypesResponse
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListVisitTypesResponseData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VisitType'
    ShowVisitTypeResponse:
      description: The response to a request a single `VisitType`
      content:
        application/json:
          schema:
            title: ShowVisitTypeResponse
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowVisitTypeResponseData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VisitType'
    ListVoucherTypes:
      description: A paginated list of `VoucherType`s for the requested site.
      content:
        application/json:
          schema:
            type: object
            title: ListVoucherTypes
            additionalProperties: false
            properties:
              data:
                type: array
                description: The voucher types on this page, ordered by `order` then by `name`.
                items:
                  $ref: '#/components/schemas/VoucherType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowVoucherType:
      description: A single `VoucherType`.
      content:
        application/json:
          schema:
            title: ShowVoucherType
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/VoucherType'
            required:
              - data
    ShowVoucherTypeLocaleStrings:
      description: The locale strings for the voucher type were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowVoucherTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingBasicLocaleStrings'
            required:
              - data
    UpdateVoucherTypeLocaleStrings:
      description: The locale strings for the voucher type were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateVoucherTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingBasicLocaleStrings'
            required:
              - data
    ListVoucherTypeAvailabilityRules:
      description: A list of `AvailabilityRule`s configured on the `VoucherType`.
      content:
        application/json:
          schema:
            title: ListVoucherTypeAvailabilityRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The availability rules for this voucher type. Order is not guaranteed.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ShowVoucherTypeAvailabilityRule:
      description: A single `AvailabilityRule` belonging to the `VoucherType`.
      content:
        application/json:
          schema:
            title: ShowVoucherTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ListVouchers:
      description: A paginated list of imported `Voucher`s for the requested site.
      content:
        application/json:
          schema:
            title: ListVouchersResponse
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: |
                  The vouchers on this page, ordered by their MongoDB
                  insertion order (effectively chronological by import
                  time).
                items:
                  $ref: '#/components/schemas/Voucher'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowVoucherCodeLookup:
      description: |
        Details of the looked-up voucher code, including its redeemable
        balance, expiry, and the offerings it may be applied to.
      content:
        application/json:
          schema:
            title: ShowVoucherCodeLookupResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/VoucherCodeLookup'
            required:
              - data
    ShowVoucher:
      description: A single `Voucher`.
      content:
        application/json:
          schema:
            title: ShowVoucherResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Voucher'
            required:
              - data
    ListCustomers:
      description: The `Customer`s were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomers
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Customer'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCustomer:
      description: The `Customer` was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowCustomer
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Customer'
            required:
              - data
    ListAssociatedBarcodes:
      description: The barcodes associated with the customer were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListAssociatedBarcodes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AssociatedBarcode'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowAssociatedBarcode:
      description: The payment method for the wearable device was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowAssociatedBarcode
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AssociatedBarcode'
            required:
              - data
    ListCustomerMemberships:
      description: The customer's `Membership`s were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListCustomerMemberships
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Membership'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ListMarketingPreferences:
      description: The marketing preferences were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListMarketingPreferences
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MarketingPreference'
            required:
              - data
    ShowMarketingPreference:
      description: The marketing preference was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowMarketingPreference
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MarketingPreference'
            required:
              - data
    ListPaymentMethods:
      description: The `PaymentMethods` were successfully retrieved
      content:
        application/json:
          schema:
            title: ListPaymentMethods
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/PaymentMethod'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ListSiteMarketingPreferences:
      description: The marketing preferences for the site were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListSiteMarketingPreferences
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MarketingPreference'
            required:
              - data
    ListSiteMembershipTypes:
      description: The membership types for the site were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListSiteMembershipTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowMembershipType:
      description: The `MembershipType` was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowMembershipType
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipType'
            required:
              - data
    ListInventoryBrands:
      description: The inventory brands were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryBrands
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryBrand'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowInventoryBrand:
      description: The inventory brand was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryBrand
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryBrand'
            required:
              - data
    ListInventoryCategories:
      description: The inventory categories were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryCategories
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryCategory'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowInventoryCategory:
      description: The inventory category was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryCategory
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryCategory'
            required:
              - data
    ListSuppliers:
      description: The suppliers were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListSuppliers
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Supplier'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowSupplier:
      description: The supplier was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowSupplier
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Supplier'
            required:
              - data
    ListSupplierProducts:
      description: The supplier's products were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListSupplierProducts
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SupplierProduct'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ListInventoryProducts:
      description: The inventory products were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryProducts
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryProduct'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowInventoryProduct:
      description: The inventory product was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryProduct
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryProduct'
            required:
              - data
    ListInventoryProductAdjustments:
      description: The adjustments for the inventory product were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryProductAdjustments
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryProductAdjustment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowInventoryProductAdjustment:
      description: The inventory product adjustment was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryProductAdjustment
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryProductAdjustment'
            required:
              - data
    ShowInventoryProductSupplier:
      description: The inventory product supplier was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryProductSupplier
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryProductSupplier'
            required:
              - data
    ListInventoryIds:
      description: The list of inventory IDs for the current site.
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryIds
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryIdEntry'
            required:
              - data
    ListInventoryOrders:
      description: The inventory orders were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryOrders
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryOrder'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowInventoryOrder:
      description: The inventory order was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryOrder
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryOrder'
            required:
              - data
    ShowInventoryOrderWithItems:
      description: The inventory order with items was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryOrderWithItems
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryOrderWithItems'
            required:
              - data
    ListInventoryOrderItems:
      description: The inventory order items were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListInventoryOrderItems
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryOrderItem'
            required:
              - data
    ShowInventoryOrderItem:
      description: The inventory order item was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowInventoryOrderItem
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/InventoryOrderItem'
            required:
              - data
    ListStockTakes:
      description: The stocktakes were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListStockTakes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/StockTake'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowStockTake:
      description: The stocktake was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowStockTake
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/StockTake'
            required:
              - data
    ListStockTakeItems:
      description: The stock take items were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListStockTakeItems
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/StockTakeItem'
              meta:
                type: object
                title: Meta
                allOf:
                  - type: object
                    title: StockTakeItemsMeta
                    additionalProperties: false
                    properties:
                      totals:
                        $ref: '#/components/schemas/StockTakeItemsTotals'
                      currency:
                        type: string
                        description: The currency of the stock take items.
                        example: gbp
                  - $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowStockTakeItem:
      description: The stocktake item was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowStockTakeItem
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/StockTakeItem'
            required:
              - data
    ListStockOnHand:
      description: The stock on hand was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListStockOnHand
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/StockOnHand'
              meta:
                $ref: '#/components/schemas/StockOnHandMeta'
            required:
              - data
              - meta
    ListStockAdjustments:
      description: The stock adjustments were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListStockAdjustments
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/StockAdjustment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
              - meta
    AppointmentEnquiryResponse:
      description: Results of the availability check for an appointment enquiry
      content:
        application/json:
          schema:
            title: AppointmentEnquiryResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AppointmentEnquiry'
            required:
              - data
    ListCoupons:
      description: A list of coupons
      content:
        application/json:
          schema:
            title: ListCoupons
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListCouponsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Coupon'
    ShowCoupon:
      description: The coupon was successfully created
      content:
        application/json:
          schema:
            title: ShowCoupon
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowCouponData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/Coupon'
    ShowCouponLocaleStrings:
      description: The locale strings for the coupon were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCouponLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CouponLocaleStrings'
            required:
              - data
    UpdateCouponLocaleStrings:
      description: The locale strings for the coupon were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateCouponLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CouponLocaleStrings'
            required:
              - data
    ListCouponCodes:
      description: A paginated list of `CouponCode`s for the parent coupon.
      content:
        application/json:
          schema:
            title: ListCouponCodes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: |
                  The coupon codes on this page, in arbitrary order. Page
                  with `page` + `per_page` query parameters to walk the
                  full set.
                items:
                  $ref: '#/components/schemas/CouponCode'
            required:
              - data
    ShowCouponCode:
      description: A single `CouponCode`.
      content:
        application/json:
          schema:
            title: ShowCouponCode
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CouponCode'
            required:
              - data
    ShowOfferingDiscount:
      description: The offering discount was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowOfferingDiscount
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingDiscount'
            required:
              - data
    CouponCodeUsageStatsResponse:
      description: Usage statistics retrieved successfully
      content:
        application/json:
          schema:
            title: CouponCodeUsageStatsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CouponCodeUsageStats'
                nullable: true
            required:
              - data
    ListOrders:
      description: The `Order`s were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListOrders
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderV2'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowOrderV2:
      description: The `Order` was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowOrder
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OrderV2'
            required:
              - data
    PrintPosReceiptForOrderResponse:
      description: Response schema for printing a POS receipt for an order
      content:
        application/json:
          schema:
            title: PrintPosReceiptForOrderResponse
            type: object
            additionalProperties: false
            properties:
              message:
                type: string
                description: A message confirming that the receipt was printed successfully.
              preview:
                type: string
                nullable: true
                description: An HTML string of the reciept preview if the `preview` field was set to `true` in the request body. Only available for internal users, will always be `null` otherwise.
            required:
              - message
              - preview
    ListOrderPayments:
      description: A list of payments made for an order
      content:
        application/json:
          schema:
            type: object
            title: ListOrderPayments
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Payment'
            required:
              - data
    ShowOrderPayment:
      description: A single payment recorded against an order.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrderPayment
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Payment'
            required:
              - data
    ShowOrder:
      description: The `Order` was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowOrder
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Order'
            required:
              - data
    ShowPostingRoom:
      description: The `PostingRoom` was successfully associated to the `Order`
      content:
        application/json:
          schema:
            type: object
            title: ShowPostingRoom
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/PostingRoom'
    ApplyOrderDiscount:
      description: The `OrderDiscount` was successfully applied.
      content:
        application/json:
          schema:
            type: object
            title: ApplyOrderDiscount
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderDiscount'
    ListOrderEmails:
      description: The email messages for the order were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListOrderEmails
            additionalProperties: false
            required:
              - data
              - meta
              - links
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderEmailSummary'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
    ShowOrderEmailSummary:
      description: The email message was successfully sent.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrderEmailSummary
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/OrderEmailSummary'
    ShowOrderEmailMessage:
      description: The email message was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrderEmailMessage
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/OrderEmailMessage'
    OrderExternalIds:
      description: Contains details of the external IDs applied to an order.
      content:
        application/json:
          schema:
            type: object
            title: OrderExternalIds
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderExternalId'
    OrderFiscalReceipts:
      description: Contains an array of fiscal receipts relating to the order.
      content:
        application/json:
          schema:
            type: object
            title: OrderFiscalReceipts
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/FiscalReceipt'
            required:
              - data
    ListOrderGuests:
      description: The guests on the order were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListOrderGuests
            additionalProperties: false
            required:
              - data
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Guest'
    ShowOrderGuest:
      description: The guest was successfully created or updated.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrderGuest
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/Guest'
    OrderItem:
      description: Describes a line item within an order.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrderItem
            additionalProperties: false
            properties:
              data:
                description: |
                  The order line item record. The concrete shape depends on
                  the item type — bookings (appointments, sessions, area
                  bookings), purchases (retail products, vouchers), or
                  packages.
                allOf:
                  - $ref: '#/components/schemas/BookingOrderItem'
                  - $ref: '#/components/schemas/PurchaseOrderItem'
                  - $ref: '#/components/schemas/PackageOrderItem'
            required:
              - data
    ApplyOrderItemDiscount:
      description: The `OrderItemDiscount` was successfully applied.
      content:
        application/json:
          schema:
            type: object
            title: ApplyOrderItemDiscount
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OrderItemDiscount'
    ShowOrderLabel:
      description: The label that was attached to the order.
      content:
        application/json:
          schema:
            title: ShowOrderLabel
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_Label'
            required:
              - data
    ListOrderNotes:
      description: The order notes were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListOrderNotes
            additionalProperties: false
            required:
              - data
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderNote'
    ShowOrderNote:
      description: The order note was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrderNote
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/OrderNote'
    ListOrderMessages:
      description: The order messages were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListOrderMessages
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderMessageSummary'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    GetNextAutomatedOrderMessage:
      description: |
        The date and time for when the next automated order message will be sent.
      content:
        application/json:
          schema:
            type: object
            title: GetNextAutomatedOrderMessage
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AutomatedOrderMessage'
            required:
              - data
    ListSmsMessages:
      description: The SMS messages were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListSmsMessages
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SmsMessageSummary'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowSmsMessage:
      description: The SMS message was successfully sent
      content:
        application/json:
          schema:
            type: object
            title: ShowSmsMessage
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SmsMessageSummary'
            required:
              - data
    PreviewSmsMessage:
      description: The preview of the SMS message was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: PreviewSmsMessage
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SmsMessagePreview'
            required:
              - data
    ShowSmsMessageSuppressionStatus:
      description: The suppression status of the SMS message was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowSmsMessageSuppressionStatus
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SmsMessageSuppressionStatus'
            required:
              - data
    CustomerSummary:
      description: A summary of a customer
      content:
        application/json:
          schema:
            type: object
            title: CustomerSummary
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_CustomerSummary-2'
    ListCategories:
      description: The categories were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListCategories
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_Category-3'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCategory:
      description: The category was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowCategory
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_Category-3'
            required:
              - data
    OrderedCategories:
      description: The ordered categories were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: OrderedCategories
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_Category-3'
            required:
              - data
    ShowCategoryLocaleStrings:
      description: The locale strings for the category were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCategoryLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CategoryLocaleStrings'
            required:
              - data
          example:
            data:
              name: Massages
    UpdateCategoryLocaleStrings:
      description: The locale strings for the category were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateCategoryLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CategoryLocaleStrings'
            required:
              - data
          example:
            data:
              name: Massages
    ListCustomPaymentTypes:
      description: The custom payment types were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListCustomPaymentTypes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomPaymentType'
            required:
              - data
    ShowCustomPaymentType:
      description: The custom payment type was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCustomPaymentType
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomPaymentType'
            required:
              - data
    ListSessionTypes:
      description: The Session Types were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListSessionTypes
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListSessionTypesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/SessionType'
    ListSessionTypePriceRules:
      description: A list of price rules for a session type.
      content:
        application/json:
          schema:
            title: ListSessionTypePriceRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_PriceRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              total:
                type: integer
                description: The total number of price rules for this session type without filters applied.
            required:
              - data
              - meta
              - total
    ShowSessionTypePriceRule:
      description: A single `PriceRule` on a `SessionType`.
      content:
        application/json:
          schema:
            title: ShowSessionTypePriceRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PriceRule'
            required:
              - data
    ShowSessionTypeLocaleStrings:
      description: The locale strings for the session type were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowSessionTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    UpdateSessionTypeLocaleStrings:
      description: The locale strings for the session type were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateSessionTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingLocaleStrings'
            required:
              - data
    ShowAppointmentEnquirySettings:
      description: A response containing a site's appointment enquiry settings.
      content:
        application/json:
          schema:
            title: ShowAppointmentEnquirySettings
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AppointmentEnquirySettings'
            required:
              - data
    ListRevenueCentres:
      description: A list of all revenue centres for a `Site`.
      content:
        application/json:
          schema:
            type: object
            title: ListRevenueCentres
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/RevenueCentre'
              meta:
                type: object
                title: ListRevenueCentresMeta
                additionalProperties: false
                properties:
                  has_custom_revenue_centres:
                    type: boolean
                    description: Whether the revenue centres have been overridden from Trybe defaults
                    example: true
            required:
              - data
              - meta
    ShowRevenueCentre:
      description: Details of a single revenue centre.
      content:
        application/json:
          schema:
            type: object
            title: ShowRevenueCentre
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/RevenueCentre'
            required:
              - data
    ShowServiceChargeSettings:
      description: A response containing a site's service charge settings.
      content:
        application/json:
          schema:
            title: ShowServiceChargeSettings
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/ServiceChargeSettings'
            required:
              - data
    ShowAutoCheckoutSettings:
      description: A response containing a site's auto checkout settings.
      content:
        application/json:
          schema:
            title: ShowAutoCheckoutSettings
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AutoCheckoutSettings'
            required:
              - data
    ShowSmsNotificationSettings:
      description: The SMS Notification Settings were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowSmsNotificationSettings
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SmsNotificationSettings'
            required:
              - data
    ListSupportedCommsLocales:
      description: A list of supported comms locales
      content:
        application/json:
          schema:
            title: ListSupportedCommsLocales
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SupportedLocale'
    ShowSiteLegalLocaleStrings:
      description: The legal locale strings for the site were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowSiteLegalLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SiteLegalLocaleStrings'
            required:
              - data
    UpdateSiteLegalLocaleStrings:
      description: The legal locale strings for the site were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateSiteLegalLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SiteLegalLocaleStrings'
            required:
              - data
    ShowSiteFeatures:
      description: The `Site` features were successfully retrieved
      content:
        application/json:
          schema:
            title: ShowSiteFeatures
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SiteFeatures'
            required:
              - data
    ShowOfferingOrder:
      description: The order of offerings available on the shop for the site.
      content:
        application/json:
          schema:
            type: object
            title: ShowOfferingOrder
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingSearchResult'
            required:
              - data
    ShowSsoConfig:
      description: The SSO configuration for the site.
      content:
        application/json:
          schema:
            type: object
            title: ShowSsoConfig
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SsoConfig'
            required:
              - data
    ListMessageFragments:
      description: The message fragments were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListMessageFragments
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MessageFragment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowMessageFragment:
      description: The message fragment was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowMessageFragment
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MessageFragment'
            required:
              - data
    ShowMessageFragmentLocaleStrings:
      description: The locale strings for the message fragment were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowMessageFragmentLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MessageFragmentLocaleStrings'
            required:
              - data
    UpdateMessageFragmentLocaleStrings:
      description: The locale strings for the message fragment were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateMessageFragmentLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MessageFragmentLocaleStrings'
            required:
              - data
    ListSmsFragments:
      description: The SMS Message Fragments were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListSmsFragments
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SmsFragment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowSmsFragment:
      description: The SMS Message Fragment was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowSmsFragment
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SmsFragment'
            required:
              - data
    SmartFiltersResponse:
      description: A response with a list of smart filters to be used on a list report.
      content:
        application/json:
          schema:
            title: SmartFiltersResponse
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SmartFilter'
            required:
              - data
    PractitionerOccupancyReportResponse:
      description: Practitioner occupancy report data.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PractitionerOccupancyReport'
        text/csv:
          schema:
            title: PractitionerOccupancyReportResponseCSV
            additionalProperties: false
            type: string
            description: CSV file contents of the practitioner occupancy report.
    PractitionerOccupancyQueuedJobResponse:
      description: The report has been queued for export.
      content:
        application/json:
          schema:
            title: PractitionerOccupancyQueuedJobResponse
            additionalProperties: false
            type: object
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/QueuedJob'
    PractitionerOccupancyByDateReportResponse:
      description: Practitioner occupancy by date report data.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PractitionerOccupancyByDateReport'
        text/csv:
          schema:
            title: PractitionerOccupancyByDateReportResponseCSV
            additionalProperties: false
            type: string
            description: CSV file contents of the practitioner occupancy by date report.
    PractitionerOccupancyByDateQueuedJobResponse:
      description: The report has been queued for export.
      content:
        application/json:
          schema:
            title: PractitionerOccupancyByDateQueuedJobResponse
            additionalProperties: false
            type: object
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/QueuedJob'
    ListUsedPromoCodesSummary:
      description: The summary of Used Promo Codes was successfully retrieved
      content:
        application/json:
          schema:
            title: ListUsedPromoCodesSummary
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/UsedPromoCodeSummary'
            required:
              - data
        text/csv:
          schema:
            type: string
    ListUsedPromoCodesBreakdown:
      description: The breakdown of `UsedPromoCodes` was successfully retrieved
      content:
        application/json:
          schema:
            title: ListUsedPromoCodesBreakdown
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/UsedPromoCodeBreakdown'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
        text/csv:
          schema:
            type: string
    ListUsedDiscountTypesSummary:
      description: The summary of Used Discount Types was successfully retrieved
      content:
        application/json:
          schema:
            title: ListUsedDiscountTypesSummary
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/UsedDiscountTypeSummary'
            required:
              - data
        text/csv:
          schema:
            type: string
    ListUsedDiscountTypesBreakdown:
      description: The breakdown of `UsedDiscountTypes` was successfully retrieved
      content:
        application/json:
          schema:
            title: ListUsedDiscountTypesBreakdown
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/UsedDiscountTypeBreakdown'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
        text/csv:
          schema:
            type: string
    ListRevenueByCentreSummary:
      description: The revenue by centre summary was successfully retrieved
      content:
        application/json:
          schema:
            title: ListRevenueByCentreSummary
            additionalProperties: false
            type: object
            properties:
              data:
                $ref: '#/components/schemas/RevenueByCentreSummary'
              meta:
                $ref: '#/components/schemas/RevenueByCentreMeta'
            required:
              - data
              - meta
        text/csv:
          schema:
            type: string
    OrganisationRevenueByCentreResponse:
      description: Contains the report data
      content:
        application/json:
          schema:
            title: OrganisationRevenueByCentreResponse
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrganisationRevenueByCentreSiteStats'
              totals:
                $ref: '#/components/schemas/OrganisationRevenueByCentreTotals'
              meta:
                $ref: '#/components/schemas/OrganisationRevenueByCentreMeta'
            required:
              - data
              - totals
              - meta
    AuthenticationLogResponse:
      description: Contains the report data
      content:
        application/json:
          schema:
            title: AuthenticationLogResponse
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AuthenticationLog'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
        text/csv:
          schema:
            type: string
    OrganisationRevenueBySalesChannelResponse:
      description: Contains the report data
      content:
        application/json:
          schema:
            title: OrganisationRevenueBySalesChannelResponse
            additionalProperties: false
            type: object
            properties:
              data:
                $ref: '#/components/schemas/OrganisationRevenueBySalesChannelStats'
              meta:
                $ref: '#/components/schemas/OrganisationRevenueBySalesChannelMeta'
            required:
              - data
              - meta
    OrganisationTopOfferingsResponse:
      description: Contains the report data
      content:
        application/json:
          schema:
            title: OrganisationTopOfferingsResponse
            additionalProperties: false
            type: object
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrganisationTopOfferingsOffering'
              totals:
                $ref: '#/components/schemas/OrganisationTopOfferingsTotals'
              meta:
                $ref: '#/components/schemas/OrganisationTopOfferingsMeta'
            required:
              - data
              - totals
              - meta
    KpiStatsResponse:
      description: KPI stats report data.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/KpiStatsReport'
    ListMemberships:
      description: The `Membership`s were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListMemberships
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Membership'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowMembership:
      description: The `Membership` was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowMembership
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Membership'
            required:
              - data
    ListMembershipTypes:
      description: The `MembershipType`s were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListMembershipTypes
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipType'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowMembershipTypeLocaleStrings:
      description: The locale strings for the membership type were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowMembershipTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipTypeLocaleStrings'
            required:
              - data
    UpdateMembershipTypeLocaleStrings:
      description: The locale strings for the membership type were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateMembershipTypeLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipTypeLocaleStrings'
            required:
              - data
    ListMembershipRates:
      description: The `MembershipRate`s were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListMembershipRates
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipRate'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowMembershipRate:
      description: The `MembershipRate` was successfully retrieved or updated.
      content:
        application/json:
          schema:
            title: ShowMembershipRate
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipRate'
            required:
              - data
    ListMembershipCreditRules:
      description: The membership credit rules were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListMembershipCreditRules
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipCreditRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowMembershipCreditRule:
      description: The membership credit rule was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowMembershipCreditRule
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipCreditRule'
            required:
              - data
    MembershipChargeResponse:
      description: A charge against a membership.
      content:
        application/json:
          schema:
            type: object
            title: MembershipChargeResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipCharge'
            required:
              - data
    ShowMembershipSms:
      description: The SMS message was successfully sent
      content:
        application/json:
          schema:
            type: object
            title: ShowMembershipSms
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipSmsMessageSummary'
            required:
              - data
    PreviewMembershipSms:
      description: The preview of the SMS message was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: PreviewMembershipSms
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipSmsMessagePreview'
            required:
              - data
    ListUsers:
      description: A list of users
      content:
        application/json:
          schema:
            title: ListUsers
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListUsersData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
    ShowUser:
      description: A User
      content:
        application/json:
          schema:
            title: ShowUser
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowUserData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/User'
    ListRoles:
      description: The roles were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListRoles
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListRolesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/schemas_Role'
    ShowRole:
      description: The role was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowRole
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowRoleData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/schemas_Role'
    ListPermissions:
      description: The permissions were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListPermissions
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ListPermissionsData
                type: object
                additionalProperties: false
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Permission'
    ListCommissionPackages:
      description: The `CommissionPackage`s were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListCommissionPackages
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CommissionPackage'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCommissionPackage:
      description: The `CommissionPackage` was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowCommissionPackage
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CommissionPackage'
            required:
              - data
    ListUserCommissionAssignments:
      description: The `UserCommissionAssignment`s were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListUserCommissionAssignments
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/UserCommissionAssignment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowUserCommissionAssignment:
      description: The `UserCommissionAssignment` was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowUserCommissionAssignment
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/UserCommissionAssignment'
            required:
              - data
    ListOfferingSets:
      description: The `OfferingSet`s were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListOfferingSets
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingSet'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowOfferingSet:
      description: The `OfferingSet` was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowOfferingSet
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/OfferingSet'
            required:
              - data
    ShowAppointmentEnquiry:
      description: The `AppointmentEnquiry` was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowAppointmentEnquiry
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AppointmentEnquiry'
            required:
              - data
    ListAppointmentSlots:
      description: The list of available appointment slots was successfully retrieved.
      content:
        application/json:
          schema:
            title: ListAppointmentSlots
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AppointmentSlot'
            required:
              - data
    ListAreaBookingSlots:
      description: The list of available area-booking slots was successfully retrieved.
      content:
        application/json:
          schema:
            title: ListAreaBookingSlots
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AreaBookingSlot'
            required:
              - data
    ListAppointmentTags:
      description: The appointment tags were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListAppointmentTags
            additionalProperties: false
            required:
              - data
              - meta
              - links
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AppointmentTag'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
    ShowAppointmentTag:
      description: The appointment tag was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowAppointmentTag
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/AppointmentTag'
    ListOrganisationLabels:
      description: The labels were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListOrganisationLabels
            additionalProperties: false
            required:
              - data
              - meta
              - links
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrganisationLabel'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
    ShowOrganisationLabel:
      description: The label was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrganisationLabel
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/OrganisationLabel'
    ListOrganisationRevenueCentres:
      description: The revenue centres were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListOrganisationRevenueCentres
            additionalProperties: false
            required:
              - data
              - meta
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrganisationRevenueCentre'
              meta:
                type: object
                title: ListOrganisationRevenueCentresMeta
                additionalProperties: false
                required:
                  - has_custom_revenue_centres
                properties:
                  has_custom_revenue_centres:
                    type: boolean
                    description: |
                      Whether the revenue centres have been overridden from
                      Trybe defaults. `false` means the organisation is
                      still using the system default set; `true` means
                      custom centres have been added or existing ones
                      updated.
                    example: true
    ShowOrganisationRevenueCentre:
      description: The revenue centre was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowOrganisationRevenueCentre
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/OrganisationRevenueCentre'
    ListSalesChannels:
      description: The sales channels were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ListSalesChannels
            additionalProperties: false
            required:
              - data
              - meta
              - links
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_SalesChannel-2'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
    ShowSalesChannel:
      description: The sales channel was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: ShowSalesChannel
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/schemas_SalesChannel-2'
    ListPackageAvailabilityRules:
      description: A paginated list of `AvailabilityRule`s on a `Package`.
      content:
        application/json:
          schema:
            title: ListPackageAvailabilityRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The availability rules configured for this package on the current page.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
              - meta
    ShowPackageAvailabilityRule:
      description: A single `AvailabilityRule` belonging to a `Package`.
      content:
        application/json:
          schema:
            title: ShowPackageAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AvailabilityRule'
            required:
              - data
    ListPackageItemChoices:
      description: A list of `PackageItemChoice`s configured on a `Package`.
      content:
        application/json:
          schema:
            title: ListPackageItemChoices
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The item choices configured on this package, in their customer-facing order.
                items:
                  $ref: '#/components/schemas/PackageItemChoice'
            required:
              - data
    ShowPackageItemChoice:
      description: A single `PackageItemChoice` on a `Package`.
      content:
        application/json:
          schema:
            title: ShowPackageItemChoice
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/PackageItemChoice'
            required:
              - data
    ListPackagePriceRules:
      description: A paginated list of price rules for a package.
      content:
        application/json:
          schema:
            title: ListPackagePriceRules
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The price rules configured for this package on the current page.
                items:
                  $ref: '#/components/schemas/schemas_PriceRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
              - meta
    ShowPackagePriceRule:
      description: A single `PriceRule` belonging to a `Package`.
      content:
        application/json:
          schema:
            title: ShowPackagePriceRule
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_PriceRule'
            required:
              - data
    ListBlockedTimePresets:
      description: A paginated list of `BlockedTimePreset`s at the site.
      content:
        application/json:
          schema:
            title: ListBlockedTimePresets
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The presets on this page, alphabetised by name.
                items:
                  $ref: '#/components/schemas/BlockedTimePreset'
            required:
              - data
    ShowBlockedTimePreset:
      description: A single `BlockedTimePreset`.
      content:
        application/json:
          schema:
            title: ShowBlockedTimePreset
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/BlockedTimePreset'
            required:
              - data
    ListBlockedTimes:
      description: A list of `BlockedTime`s falling within the requested date range.
      content:
        application/json:
          schema:
            title: ListBlockedTimes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: Blocked times intersecting the requested range.
                items:
                  $ref: '#/components/schemas/BlockedTime'
            required:
              - data
    ShowBlockedTime:
      description: A single `BlockedTime`.
      content:
        application/json:
          schema:
            title: ShowBlockedTime
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/BlockedTime'
            required:
              - data
    ListCourseTypes:
      description: A paginated list of `CourseType`s for the requested site.
      content:
        application/json:
          schema:
            title: ListCourseTypes
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                type: array
                description: The course types on this page, ordered by name.
                items:
                  $ref: '#/components/schemas/CourseType'
    ListAppointmentSlotsByRange:
      description: |
        A list of bookable `AppointmentAvailabilitySlot`s plus a
        `meta` block with the practitioner roster and selection mode.
      content:
        application/json:
          schema:
            title: ListAppointmentSlotsByRange
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AppointmentAvailabilitySlot'
              meta:
                $ref: '#/components/schemas/AppointmentSlotsMeta'
            required:
              - data
    ListAreaBookingSlotsByRange:
      description: |
        A list of `AreaBookingAvailabilitySlot`s for the requested day.
        Slots are ordered earliest first, then shortest first when
        start times match.
      content:
        application/json:
          schema:
            title: ListAreaBookingSlotsByRange
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AreaBookingAvailabilitySlot'
            required:
              - data
    ListMultiAppointmentSlots:
      description: |
        A list of `MultiAppointmentSlotGroup`s — one per common start
        time that can host every requested appointment type in
        sequence.
      content:
        application/json:
          schema:
            title: ListMultiAppointmentSlots
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MultiAppointmentSlotGroup'
            required:
              - data
    ListOfferingDates:
      description: |
        Per-day availability for an offering across the requested
        date range. Each entry is one calendar day.
      content:
        application/json:
          schema:
            title: ListOfferingDates
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingDateAvailability'
              meta:
                type: object
                additionalProperties: true
                description: |
                  Booking-window metadata derived from the offering —
                  `min_advance_bookings_interval`,
                  `max_advance_bookings_interval`, `currency`, and
                  practitioner roster for appointment types.
            required:
              - data
    ListPackageChoiceSlots:
      description: |
        Bookable slots for a single package choice, indexed by
        `package_item_id`.
      content:
        application/json:
          schema:
            title: ListPackageChoiceSlots
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/PackageChoiceSlot'
            required:
              - data
    ShowProductAvailability:
      description: Current stock availability for the requested `Product`.
      content:
        application/json:
          schema:
            title: ShowProductAvailability
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/ProductStockAvailability'
            required:
              - data
    ListSessionOccurrences:
      description: A list of `SessionAvailabilityOccurrence`s for the requested window.
      content:
        application/json:
          schema:
            title: ListSessionOccurrences
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SessionAvailabilityOccurrence'
            required:
              - data
    CreateOrderCheckoutLink:
      description: A short-lived hosted-checkout URL for the order.
      content:
        application/json:
          schema:
            title: CreateOrderCheckoutLink
            type: object
            additionalProperties: false
            properties:
              url:
                type: string
                format: uri
                description: |
                  The signed checkout URL. Valid for 15 minutes from
                  issue. Share with the customer via email or SMS to hand
                  off the payment step.
                example: https://example.trybe.app/checkout/hydrate?...
            required:
              - url
    RecalculateOrderDiscount:
      description: The discount was successfully recalculated.
      content:
        application/json:
          schema:
            title: RecalculateOrderDiscount
            type: object
            additionalProperties: false
            properties:
              data:
                allOf:
                  - $ref: '#/components/schemas/OrderDiscount'
                description: |
                  The order discount with refreshed `calculated_amount`
                  and line allocations. `discount_type_code`,
                  `amount_type` and `discount_amount` are unchanged from
                  the original application.
            required:
              - data
    ShowOrderItinerary:
      description: The order's itinerary grouped by guest and date.
      content:
        application/json:
          schema:
            title: ShowOrderItinerary
            type: object
            additionalProperties: false
            properties:
              data:
                type: object
                description: |
                  A map keyed by guest bucket identifier. Each entry
                  describes the bookings belonging to one or more guests
                  who share an arrival pattern.
                additionalProperties:
                  $ref: '#/components/schemas/OrderItineraryGuestBucket'
            required:
              - data
    GetOrderItineraryDoc:
      description: A short-lived download URL for the itinerary document.
      content:
        application/json:
          schema:
            title: GetOrderItineraryDoc
            type: object
            additionalProperties: false
            properties:
              data:
                type: object
                title: GetOrderItineraryDocData
                additionalProperties: false
                properties:
                  download_url:
                    type: string
                    format: uri
                    description: |
                      Signed URL the operator can use to download the
                      generated Word document. Treat as single-use; mint
                      a fresh one for each download.
                required:
                  - download_url
            required:
              - data
    ListOrderLedgerLines:
      description: The ledger lines for the order.
      content:
        application/json:
          schema:
            title: ListOrderLedgerLines
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderLedgerLine'
            required:
              - data
    CreateOrderOverpaymentVoucher:
      description: A new voucher was issued for the order's overpayment.
      content:
        application/json:
          schema:
            title: CreateOrderOverpaymentVoucher
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/VoucherCode'
            required:
              - data
    CreateOrderPaymentRefund:
      description: The refund was successfully created.
      content:
        application/json:
          schema:
            title: CreateOrderPaymentRefundResponse
            type: object
            additionalProperties: false
            properties:
              data:
                allOf:
                  - $ref: '#/components/schemas/Refund'
                description: |
                  The freshly created `Refund` record with its assigned
                  `id`, `status`, `amount`, and processor metadata. The
                  parent payment's `refundable_amount` is decremented by
                  the refund amount in the same transaction.
            required:
              - data
    ListOrderPostings:
      description: The PMS postings recorded against the order.
      content:
        application/json:
          schema:
            title: ListOrderPostings
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderLedgerLinePosting'
            required:
              - data
    ListOrderRefundableItems:
      description: |
        The items on the order that can currently be refunded, together
        with service-charge and tip lines when they carry a positive
        balance.
      content:
        application/json:
          schema:
            title: ListOrderRefundableItems
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderRefundableItem'
            required:
              - data
    ListOrderRefunds:
      description: The refunds recorded against the order.
      content:
        application/json:
          schema:
            title: ListOrderRefunds
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Refund'
            required:
              - data
    ShowOrderRefund:
      description: A single refund recorded against an order.
      content:
        application/json:
          schema:
            title: ShowOrderRefund
            type: object
            additionalProperties: false
            properties:
              data:
                allOf:
                  - $ref: '#/components/schemas/Refund'
                description: |
                  The `Refund` record with its amount, status, the
                  payment it was issued against, and any processor-
                  specific data used by downstream reconciliation jobs.
            required:
              - data
    ListOrderRevenues:
      description: The revenue breakdown for the order, grouped by revenue centre.
      content:
        application/json:
          schema:
            title: ListOrderRevenues
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderRevenue'
              meta:
                type: object
                title: ListOrderRevenuesMeta
                additionalProperties: false
                properties:
                  currency:
                    $ref: '#/components/schemas/properties_currency'
                required:
                  - currency
            required:
              - data
              - meta
    ListShopAppointmentTags:
      description: A list of `AppointmentTag`s for the organisation.
      content:
        application/json:
          schema:
            title: ListShopAppointmentTags
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/ShopAppointmentTag'
            required:
              - data
    ListShopAppointmentTypes:
      description: A list of public-facing `AppointmentType`s.
      content:
        application/json:
          schema:
            title: ListShopAppointmentTypes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: Appointment types at the requested site.
                items:
                  $ref: '#/components/schemas/AppointmentType'
            required:
              - data
    ListShopCategories:
      description: A list of `Category`s for the organisation.
      content:
        application/json:
          schema:
            title: ListShopCategories
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/ShopCategory'
            required:
              - data
    ListShopOfferings:
      description: |
        A list of public-facing `Offering`s at the given site. Each
        entry can be an appointment, area booking, package, session, or
        product — the concrete shape varies per offering type.
      content:
        application/json:
          schema:
            title: ListShopOfferings
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: The offerings on this page.
                items:
                  oneOf:
                    - $ref: '#/components/schemas/Appointment'
                    - $ref: '#/components/schemas/AreaBooking'
                    - $ref: '#/components/schemas/Package'
                    - $ref: '#/components/schemas/Product'
                    - $ref: '#/components/schemas/Session'
            required:
              - data
    ListShopPractitioners:
      description: |
        A list of `Practitioner`s with public-facing fields suitable for
        the booking storefront.
      content:
        application/json:
          schema:
            title: ListShopPractitioners
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: Practitioners at the requested site.
                items:
                  $ref: '#/components/schemas/ShopPractitioner'
            required:
              - data
    ListCrossOrganisationCouponCodes:
      description: |
        A paginated list of coupon codes visible to the calling user across
        every organisation they are scoped to.
      content:
        application/json:
          schema:
            title: ListCrossOrganisationCouponCodes
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListCrossOrganisationCouponCodesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    description: The coupon codes on this page.
                    items:
                      $ref: '#/components/schemas/CrossOrganisationCouponCode'
    ShowCouponCodeOfferingDiscount:
      description: |
        The first `OfferingDiscount` configured on the coupon backing the
        given code. Returned as a singleton (not an array) because the
        endpoint surfaces the primary discount eligibility for point-of-sale
        UIs.
      content:
        application/json:
          schema:
            title: ShowCouponCodeOfferingDiscount
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowCouponCodeOfferingDiscountData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/OfferingDiscount'
    ListOfferingAvailabilityDays:
      description: |
        Per-day availability summary for every day in the targeted month.
      content:
        application/json:
          schema:
            title: ListOfferingAvailabilityDays
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                description: One entry per day of the month.
                items:
                  $ref: '#/components/schemas/OfferingAvailabilityDay'
            required:
              - data
    ListOrderIntakeForms:
      description: |
        Per-guest intake-form status entries for the order. One entry per
        guest + form combination — see `OrderIntakeForm` for the full
        shape semantics.
      content:
        application/json:
          schema:
            title: ListOrderIntakeForms
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/OrderIntakeForm'
            required:
              - data
    ListCheckIns:
      description: The check-ins were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCheckIns
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CheckIn'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCheckIn:
      description: The check-in was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowCheckIn
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CheckIn'
            required:
              - data
    ListCustomerAddresses:
      description: The customer's addresses were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomerAddresses
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerAddress'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
              - meta
    ShowCustomerAddress:
      description: The customer's address was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowCustomerAddress
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerAddress'
            required:
              - data
    ListCustomerAssociatedBarcodes:
      description: The associated barcodes were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomerAssociatedBarcodes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/AssociatedBarcode'
            required:
              - data
    ShowCustomerAssociatedBarcode:
      description: The associated barcode was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowCustomerAssociatedBarcode
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/AssociatedBarcode'
            required:
              - data
    ListCustomerCredits:
      description: The customer's credits were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomerCredits
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerCredit'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
              - meta
    ShowCustomerCredit:
      description: The customer's credit was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowCustomerCredit
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerCredit'
            required:
              - data
    ListCustomerAttachedLabels:
      description: The customer's labels were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomerAttachedLabels
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_CustomerLabel'
            required:
              - data
    ListCustomerMarketingPreferences:
      description: The customer's marketing preferences were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomerMarketingPreferences
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerMarketingPreferenceOptIn'
            required:
              - data
    ShowCustomerMarketingPreference:
      description: The customer's marketing preference state was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowCustomerMarketingPreference
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerMarketingPreferenceOptIn'
            required:
              - data
    ListCustomerNotes:
      description: The customer's notes were successfully retrieved
      content:
        application/json:
          schema:
            title: ListCustomerNotes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerNote'
            required:
              - data
    ShowCustomerNote:
      description: The customer's note was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowCustomerNote
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerNote'
            required:
              - data
    ListLabels:
      description: The labels were successfully retrieved
      content:
        application/json:
          schema:
            title: ListLabels
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_Label-2'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowLabel:
      description: The label was successfully retrieved
      content:
        application/json:
          schema:
            title: ShowLabel
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/schemas_Label-2'
            required:
              - data
    ShowMembershipCharge:
      description: The `MembershipCharge` was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowMembershipCharge
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipCharge'
            required:
              - data
    ShowMembershipChargeReceipt:
      description: The membership charge receipt URL was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowMembershipChargeReceipt
            type: object
            additionalProperties: false
            properties:
              data:
                title: ShowMembershipChargeReceiptData
                type: object
                additionalProperties: false
                properties:
                  download_url:
                    type: string
                    description: |
                      A temporary URL which can be used to download the PDF. This link will expire in 10
                      minutes from the time it was requested.
                required:
                  - download_url
            required:
              - data
    ShowMembershipRateLocaleStrings:
      description: The locale strings for the membership rate were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowMembershipRateLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipRateLocaleStrings'
            required:
              - data
    UpdateMembershipRateLocaleStrings:
      description: The locale strings for the membership rate were successfully updated.
      content:
        application/json:
          schema:
            title: UpdateMembershipRateLocaleStringsResponse
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipRateLocaleStrings'
            required:
              - data
    ShowMembershipRateTotals:
      description: The membership rate totals were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowMembershipRateTotals
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipRateTotals'
            required:
              - data
    ShowStripeCheckoutSession:
      description: The Stripe Checkout session was successfully created.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/StripeCheckoutSession'
    ListMembershipMembers:
      description: The list of `MembershipMember`s for the given membership was successfully retrieved.
      content:
        application/json:
          schema:
            title: ListMembershipMembers
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipMember'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
    ShowMembershipMember:
      description: The `MembershipMember` was successfully retrieved or updated.
      content:
        application/json:
          schema:
            title: ShowMembershipMember
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MembershipMember'
            required:
              - data
    ShowNextBillingDetails:
      description: The next billing details for the membership were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowNextBillingDetails
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/NextBillingDetails'
            required:
              - data
    ShowSubsequentBillingDate:
      description: The subsequent billing date for the membership was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowSubsequentBillingDate
            type: object
            additionalProperties: false
            properties:
              data:
                type: string
                format: date
                description: |
                  This is the subsequent billing date for a membership. If this value is null, the membership
                  is not active.
                nullable: true
            required:
              - data
    ShowSubsequentBillingDetails:
      description: The subsequent billing details for the membership were successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowSubsequentBillingDetails
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SubsequentBillingDetails'
            required:
              - data
    ListMyAccountCharges:
      description: The customer's charges were successfully retrieved
      content:
        application/json:
          schema:
            title: ListMyAccountCharges
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipCharge'
            required:
              - data
    ListMyAccountCredits:
      description: The customer's credits were successfully retrieved
      content:
        application/json:
          schema:
            title: ListMyAccountCredits
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerCredit'
            required:
              - data
    ListMyAccountMarketingPreferences:
      description: The customer's marketing preferences were successfully retrieved
      content:
        application/json:
          schema:
            title: ListMyAccountMarketingPreferences
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerMarketingPreferenceOptIn'
            required:
              - data
    ListMyAccountMemberships:
      description: The customer's memberships were successfully retrieved
      content:
        application/json:
          schema:
            title: ListMyAccountMemberships
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Membership'
            required:
              - data
    ListMyAccountPaymentMethods:
      description: The customer's payment methods were successfully retrieved
      content:
        application/json:
          schema:
            title: ListMyAccountPaymentMethods
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/PaymentMethod'
            required:
              - data
    ListSubscriptions:
      description: The subscriptions were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListSubscriptions
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Subscription'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
            required:
              - data
    ShowSubscription:
      description: The subscription was successfully retrieved or created.
      content:
        application/json:
          schema:
            title: ShowSubscription
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Subscription'
            required:
              - data
    ShowPaymentMethod:
      description: The `PaymentMethod` was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowPaymentMethod
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/PaymentMethod'
            required:
              - data
    ListSignupTokens:
      description: The signup tokens were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListSignupTokens
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SignupToken'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
    ShowSignupToken:
      description: The signup token was successfully retrieved or updated.
      content:
        application/json:
          schema:
            title: ShowSignupToken
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/SignupToken'
            required:
              - data
    ShowMobilePassCustomisation:
      description: The mobile pass customisation for the site was successfully retrieved or updated.
      content:
        application/json:
          schema:
            title: ShowMobilePassCustomisation
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/MobilePassCustomisation'
            required:
              - data
    ListInventoryAdjustments:
      description: Adjustments were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListInventoryAdjustments
            type: object
            additionalProperties: false
            required:
              - data
              - meta
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryAdjustment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
    ShowInventoryAdjustment:
      description: A single inventory adjustment.
      content:
        application/json:
          schema:
            title: ShowInventoryAdjustment
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/InventoryAdjustment'
    ListInventoryLocations:
      description: Locations were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListInventoryLocations
            type: object
            additionalProperties: false
            required:
              - data
              - meta
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryLocation'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
    ShowInventoryLocation:
      description: A single inventory location.
      content:
        application/json:
          schema:
            title: ShowInventoryLocation
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/InventoryLocation'
    ListInventoryProductSuppliers:
      description: Product suppliers were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListInventoryProductSuppliers
            type: object
            additionalProperties: false
            required:
              - data
              - meta
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/SupplierProduct'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
    ShowInventoryProductSupplierLink:
      description: A single product-supplier association.
      content:
        application/json:
          schema:
            title: ShowInventoryProductSupplierLink
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/SupplierProduct'
    ListNotifications:
      description: Notifications were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListNotifications
            type: object
            additionalProperties: false
            required:
              - data
              - meta
              - links
            properties:
              data:
                description: The array of notifications.
                type: array
                items:
                  $ref: '#/components/schemas/Notification'
              meta:
                $ref: '#/components/schemas/NotificationsMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
    ListPersonalAccessTokens:
      description: A list of personal access tokens
      content:
        application/json:
          schema:
            title: ListPersonalAccessTokens
            type: array
            items:
              $ref: '#/components/schemas/PersonalAccessToken'
    CreatePersonalAccessToken:
      description: A newly issued personal access token
      content:
        application/json:
          schema:
            title: CreatePersonalAccessTokenResponse
            type: object
            additionalProperties: false
            required:
              - token
              - accessToken
            properties:
              token:
                description: |
                  Metadata for the newly issued token — its ID, label,
                  creation timestamp and abilities. The raw secret itself
                  is returned separately as `accessToken` and must be
                  stored immediately because it cannot be retrieved again.
                allOf:
                  - $ref: '#/components/schemas/PersonalAccessToken'
              accessToken:
                type: string
                description: The raw access token. This is the only time the raw value is returned — store it securely.
                example: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjVkYTRhZmEwNjUwZGQ2MDFiNzI2Mzc0YjVmMWM2MjgyIn0.eyJhdWQiOiI5M2MwMGY1NC04NjZhLTRiMjMtYWJiYi05MmFjY
    SiteTaxInfo:
      description: The site tax info
      content:
        application/json:
          schema:
            title: ShowSiteTaxInfo
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/SiteTaxInfo'
    UserOptions:
      description: A map of options for a user
      content:
        application/json:
          schema:
            title: ShowUserOptions
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowUserOptionsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/UserOptions'
    ListPackageItemChoiceOptions:
      description: A list of `PackageItemChoiceOption`s on a `PackageItemChoice`.
      content:
        application/json:
          schema:
            title: ListPackageItemChoiceOptions
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                type: array
                description: The options for this choice.
                items:
                  $ref: '#/components/schemas/PackageItemChoiceOption'
    ShowPackageItemChoiceOption:
      description: A single `PackageItemChoiceOption`.
      content:
        application/json:
          schema:
            title: ShowPackageItemChoiceOption
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/PackageItemChoiceOption'
    ShowSessionBooking:
      description: A single `SessionBooking`.
      content:
        application/json:
          schema:
            title: ShowSessionBooking
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/SessionBooking'
    ListVisitIntakeForms:
      description: A paginated list of `VisitIntakeForm`s.
      content:
        application/json:
          schema:
            title: ListVisitIntakeForms
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListVisitIntakeFormsData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VisitIntakeForm'
    ShowVisitIntakeForm:
      description: A single `VisitIntakeForm`.
      content:
        application/json:
          schema:
            title: ShowVisitIntakeForm
            allOf:
              - $ref: '#/components/schemas/DataEnvelope'
              - title: ShowVisitIntakeFormData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/VisitIntakeForm'
    ShowVoucherPurchaseMailable:
      description: |
        A preview-ready transactional email built from the voucher
        purchase. Returned by both the preview and send endpoints.
      content:
        application/json:
          schema:
            title: ShowVoucherPurchaseMailable
            type: object
            additionalProperties: false
            required:
              - data
            properties:
              data:
                $ref: '#/components/schemas/VoucherPurchaseMailable'
        text/html:
          schema:
            type: string
    GetYieldInsights:
      description: The yield insights were successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: GetYieldInsightsResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/YieldInsights'
            required:
              - data
    GetYieldInsightsHeatmap:
      description: The demand heatmap was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: GetYieldInsightsHeatmapResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/YieldInsightsHeatmap'
            required:
              - data
    GetYieldInsightsRevenueComparison:
      description: The revenue comparison was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: GetYieldInsightsRevenueComparisonResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/YieldInsightsRevenueComparison'
            required:
              - data
    GetYieldInsightsRoomOccupancy:
      description: The room and area occupancy grid was successfully retrieved.
      content:
        application/json:
          schema:
            type: object
            title: GetYieldInsightsRoomOccupancyResponse
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/YieldInsightsRoomOccupancy'
            required:
              - data
    ListYieldRules:
      description: The yield rules were successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ListYieldRules
            additionalProperties: false
            properties:
              data:
                type: array
                description: |
                  Ordered by `updated_at` descending, so where rules conflict the one
                  that would win comes first.
                items:
                  $ref: '#/components/schemas/YieldRule'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    CreateYieldRules:
      description: |
        The yield rules were successfully created. One rule is returned per offering
        supplied, each independent of the others.
      content:
        application/json:
          schema:
            type: object
            title: CreateYieldRulesResponse
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/YieldRule'
            required:
              - data
    QueueYieldRules:
      description: |
        The selection was too large to write during the request, so the rules are
        being created by a background job. Poll the list endpoint with
        `created_batch_id` to follow them appearing.
      content:
        application/json:
          schema:
            type: object
            title: QueueYieldRulesResponse
            additionalProperties: false
            properties:
              data:
                type: object
                title: QueuedYieldRules
                additionalProperties: false
                properties:
                  created_batch_id:
                    type: string
                    format: uuid
                    description: |
                      The `created_batch_id` every rule in this batch will carry.
                  offerings:
                    type: integer
                    description: The number of rules that will be created.
                required:
                  - created_batch_id
                  - offerings
            required:
              - data
    ShowYieldRule:
      description: The yield rule was successfully retrieved
      content:
        application/json:
          schema:
            type: object
            title: ShowYieldRule
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/YieldRule'
            required:
              - data
    ShowTokenInfo:
      description: |
        The decoded JWT claims for the caller's bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/TokenInfo'
    ListMembershipCharges:
      description: The `MembershipCharge`s were successfully retrieved
      content:
        application/json:
          schema:
            title: ListMembershipCharges
            allOf:
              - $ref: '#/components/schemas/Pagination'
              - title: ListMembershipChargesData
                type: object
                additionalProperties: false
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/MembershipCharge'
    MembershipStatusChange:
      description: The membership status was recomputed.
      content:
        application/json:
          schema:
            title: MembershipStatusChange
            type: object
            additionalProperties: false
            properties:
              data:
                title: MembershipStatusChangeData
                type: object
                additionalProperties: false
                properties:
                  previous_status:
                    type: string
                    description: |
                      The `status` value the membership had before this
                      endpoint was called. Identical to `new_status` when
                      the refresh produced no change.
                    example: active
                  previous_attention_reason:
                    type: string
                    description: |
                      The `attention_reason` value the membership had
                      before this endpoint was called, or `null` if it
                      required no attention.
                    example: payment_failed
                    nullable: true
                  new_status:
                    type: string
                    description: |
                      The freshly-computed `status` for the membership.
                      Identical to `previous_status` when the refresh
                      produced no change.
                    example: needs_attention
                  new_attention_reason:
                    type: string
                    description: |
                      The freshly-computed `attention_reason`, or `null`
                      if the membership now requires no operator
                      attention.
                    example: mandate_revoked
                    nullable: true
                required:
                  - previous_status
                  - previous_attention_reason
                  - new_status
                  - new_attention_reason
            required:
              - data
    NewMembershipDetails:
      description: The signup form details were successfully retrieved.
      content:
        application/json:
          schema:
            title: NewMembershipDetails
            type: object
            additionalProperties: false
            properties:
              customer_details:
                title: NewMembershipCustomerDetails
                type: object
                additionalProperties: false
                description: |
                  Pre-filled customer details derived from a supplied
                  `MembershipSignupToken`. Only present when `token` was
                  supplied on the request — otherwise the property is
                  omitted.
                properties:
                  first_name:
                    type: string
                    description: The customer's pre-filled first name, if known.
                    nullable: true
                  last_name:
                    type: string
                    description: The customer's pre-filled last name, if known.
                    nullable: true
                  email:
                    type: string
                    format: email
                    description: The customer's pre-filled email, if known.
                    nullable: true
                  phone:
                    type: string
                    description: The customer's pre-filled phone, if known.
                    nullable: true
                required: []
              types:
                type: array
                description: |
                  The membership types available for signup at the given
                  site, in display order. When a `token` is supplied, this
                  list is narrowed to the type / rate the token is scoped
                  to.
                items:
                  $ref: '#/components/schemas/NewMembershipType'
            required:
              - types
    ListOrderedMembershipTypes:
      description: The `MembershipType`s were retrieved in display order.
      content:
        application/json:
          schema:
            title: ListOrderedMembershipTypes
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/schemas_MembershipTypeSummary-2'
            required:
              - data
    ListPublicMarketingPreferences:
      description: The public marketing preferences were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListPublicMarketingPreferences
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/PublicMarketingPreference'
            required:
              - data
    ListCustomerSegments:
      description: The customer segments were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListCustomerSegments
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerSegment'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCustomerSegment:
      description: The customer segment was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCustomerSegment
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerSegment'
            required:
              - data
    ListCustomerSegmentMembers:
      description: The segment members were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListCustomerSegmentMembers
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CustomerSegmentMember'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCustomerSegmentMember:
      description: The segment member was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCustomerSegmentMember
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CustomerSegmentMember'
            required:
              - data
    ListCampaigns:
      description: The campaigns were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListCampaigns
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/Campaign'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCampaign:
      description: The campaign was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCampaign
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/Campaign'
            required:
              - data
    ListCampaignContents:
      description: The campaign contents were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListCampaignContents
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CampaignContent'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCampaignContent:
      description: The campaign content was successfully retrieved.
      content:
        application/json:
          schema:
            title: ShowCampaignContent
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CampaignContent'
            required:
              - data
    ListCampaignSends:
      description: The campaign sends were successfully retrieved.
      content:
        application/json:
          schema:
            title: ListCampaignSends
            type: object
            additionalProperties: false
            properties:
              data:
                type: array
                items:
                  $ref: '#/components/schemas/CampaignSend'
              meta:
                $ref: '#/components/schemas/PaginationMeta'
              links:
                $ref: '#/components/schemas/PaginationLinks'
            required:
              - data
              - meta
              - links
    ShowCampaignSend:
      description: |
        The campaign send was successfully retrieved. Requesting with an `Accept: text/html`
        header returns the rendered email body as HTML instead of the `CampaignSend` record.
      content:
        application/json:
          schema:
            title: ShowCampaignSend
            type: object
            additionalProperties: false
            properties:
              data:
                $ref: '#/components/schemas/CampaignSend'
            required:
              - data
        text/html:
          schema:
            type: string
            description: The rendered HTML body of the email that was sent.
            example: <p>Hi there! We have a special offer just for you.</p>
  requestBodies:
    CreateApiUser:
      description: The details of the API user to create.
      required: true
      content:
        application/json:
          schema:
            title: CreateApiUser
            type: object
            additionalProperties: false
            required:
              - name
              - site_id
            properties:
              name:
                type: string
                description: |
                  Human-readable label for the API user. Shown in the
                  API users list and recorded against audit-log entries
                  so operators can identify which integration made a
                  change. Pick something descriptive like
                  "Mailchimp sync" or "POS terminal 3". Must be unique
                  across API users in the organisation.
                example: Mailchimp sync
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site to attach the new API user to.
                  The caller must hold the `users:manage` permission on
                  this site; the user inherits the organisation that
                  owns the site. Additional sites can be granted later
                  by an organisation admin.
    UpdateApiUser:
      description: The new values for the API user.
      required: true
      content:
        application/json:
          schema:
            title: UpdateApiUser
            type: object
            additionalProperties: false
            required:
              - name
              - site_id
            properties:
              name:
                type: string
                description: |
                  New human-readable label for the API user. Must be
                  unique across API users in the organisation.
                example: Mailchimp sync (production)
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the API user's primary site. Used to
                  validate uniqueness of `name` within the owning
                  organisation; the user's existing site memberships
                  are not changed by this field.
    CreateCalendarNote:
      description: |
        Body for creating a new `CalendarNote`. `body` and `date` are
        required. `site_id` defaults to the site from the request when
        omitted.
      required: true
      content:
        application/json:
          schema:
            title: CreateCalendarNote
            type: object
            additionalProperties: false
            properties:
              body:
                type: string
                description: |
                  The note text. Plain text only — line breaks are
                  preserved but no markdown is rendered. There is no
                  hard length limit, but keep it short so it reads well
                  in the calendar.
                example: Public holiday — front desk closes at 16:00.
              date:
                type: string
                format: date
                description: |
                  The calendar date the note applies to, in `YYYY-MM-DD`
                  format. The date is interpreted in the site's local
                  timezone.
                example: '2026-05-25'
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the site to attach the note to. The caller's API
                  key must have access to the site and the
                  `RESERVATIONS_MANAGE` permission on it. Defaults to the
                  site from the request context when omitted.
                example: 11111111-1111-1111-1111-111111111111
            required:
              - body
              - date
    UpdateCalendarNote:
      description: |
        Body for updating an existing `CalendarNote`. Every field is
        optional; omitted fields keep their current values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateCalendarNote
            type: object
            additionalProperties: false
            properties:
              body:
                type: string
                description: |
                  Replacement note text, shown to staff on the calendar
                  view. Plain text only — HTML tags are stripped.
                example: Public holiday — front desk closes at 17:00.
              date:
                type: string
                format: date
                description: |
                  Move the note to a different calendar date, in
                  `YYYY-MM-DD` format.
                example: '2026-05-26'
              site_id:
                type: string
                format: uuid
                description: |
                  Move the note to a different site. The caller's API key
                  must have access to both the old and new site.
                example: 11111111-1111-1111-1111-111111111111
    AddBasketItem:
      required: true
      content:
        application/json:
          schema:
            title: AddBasketItem
            type: object
            additionalProperties: true
            properties:
              discount_amount:
                type: integer
                nullable: true
                description: |
                  Manual discount to apply to this line item, in the smallest
                  currency unit (e.g. pence, cents). Subtracted from the line
                  subtotal before tax. Defaults to 0 / null (no discount).
                example: 500
              guest_ids:
                type: array
                items:
                  type: string
                  format: object-id
              guests:
                type: array
                items:
                  title: AddBasketItemGuest
                  type: object
                  additionalProperties: false
                  properties:
                    customer_id:
                      type: string
                      format: uuid
                    is_lead_booker:
                      type: boolean
                    name:
                      type: string
                  required:
                    - name
              offering_id:
                type: string
                format: object-id
                description: |
                  ID of the offering being added to the basket. Required for
                  every `offering_type` other than free-form vouchers. The
                  format depends on the offering type — practitioner-scheduled
                  offerings use Mongo ObjectIDs.
                example: 5f1234567890abcdef123456
              offering_type:
                $ref: '#/components/schemas/OfferingType'
              price:
                type: integer
                description: |
                  Override price for this line item in the smallest currency
                  unit (e.g. pence, cents). Omit to let the server compute the
                  price from the offering's current price rules.
                example: 4800
              quantity:
                type: integer
                description: Number of units to add to the basket. Defaults to 1.
                example: 1
            required:
              - offering_type
    CreateIdentityRequest:
      description: Create a request to identify a wearable device.
      content:
        application/json:
          schema:
            title: CreateIdentityRequest
            type: object
            additionalProperties: false
            properties:
              terminal_id:
                type: string
                format: object-id
                description: |
                  Identifier of the physical payment terminal that should
                  prompt for the wearable tap. Must be a terminal registered
                  to the caller's site; the terminal serves the prompt and
                  relays the scanned wearable's identifier back to Trybe.
            required:
              - terminal_id
    CreateWearableAssociationRequest:
      description: Create a request to associate a wearable device with a customer.
      content:
        application/json:
          schema:
            title: CreateWearableAssociationRequest
            type: object
            additionalProperties: false
            properties:
              terminal_id:
                type: string
                format: object-id
                description: |
                  Identifier of the physical terminal that should prompt
                  for the wearable tap. Must be a terminal registered to
                  the caller's site; the terminal scans the wearable and
                  completes the link to `customer_id`.
              customer_id:
                type: string
                format: uuid
                description: |
                  Identifier of the customer that the scanned wearable
                  should be linked to. Once associated, the wearable can
                  be used as a payment device for this customer's stays
                  and visits.
              order_id:
                type: string
                format: object-id
                description: |
                  Optional identifier of an order to attach the wearable
                  to at association time, useful for express check-in
                  flows. Pass `null` to leave the wearable unattached.
                nullable: true
            required:
              - terminal_id
              - customer_id
    CreateCardTokenisationRequest:
      description: Create a request to tokenise a customer's card details.
      content:
        application/json:
          schema:
            title: CreateCardTokenisationRequest
            type: object
            additionalProperties: false
            properties:
              terminal_id:
                type: string
                format: object-id
                description: |
                  Identifier of the physical payment terminal that should
                  prompt for the card. The terminal captures the card and
                  returns a tokenised reference; no PAN is stored in Trybe.
                  Must belong to the caller's site.
              customer_id:
                type: string
                format: uuid
                description: |
                  Identifier of the customer whose card is being saved on
                  file. The resulting payment-method token is attached to
                  this customer and can be used for future charges (e.g.
                  no-show fees, recurring bookings).
            required:
              - terminal_id
              - customer_id
    CreateAppointmentType:
      description: |
        Body for creating a new `AppointmentType`. `name` and `site_ids` are
        required; everything else has a sensible default or `null`-equivalent.
        See `AppointmentType` in `schemas.yml` for the full field list and
        their semantics — this body accepts the same write-able fields plus
        `site_ids` (which determines which sites the type is offered at).
      required: true
      content:
        application/json:
          schema:
            title: CreateAppointmentType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the appointment type. Visible to customers in
                  the booking flow and to staff in the admin UI. Plain text only —
                  HTML tags are rejected at validation time.
                example: Aromatherapy Massage 60 minutes
              description:
                type: string
                description: |
                  Long-form description shown to customers when they're selecting
                  the appointment type. Markdown is rendered.
                example: |
                  A relaxing aromatherapy massage using a blend of essential oils
                  tailored to your needs. Ideal for stress relief and improving
                  circulation.
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map this appointment type to an
                  external POS or PMS catalog. Free-form string; uniqueness is
                  not enforced server-side.
                example: MASSAGE-AROMA-60
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this offering. Free-form.
                example: ext-aroma-60
              currency:
                $ref: '#/components/schemas/properties_currency'
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this appointment type, in the
                  smallest currency unit (e.g. pence/cents). Optional at
                  create time — offerings can be created without a
                  standard price and have one configured later.
                example: 5000
              site_ids:
                type: array
                description: |
                  One or more site IDs to offer this appointment type at. The
                  caller's API key must have access to every listed site;
                  requests with a site they don't own get 422.
                items:
                  type: string
                  format: uuid
                minItems: 1
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation to attribute this offering to. Defaults to
                  the caller's primary organisation if omitted.
              practitioner_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: |
                  Practitioners who can perform this appointment type. Only
                  practitioners belonging to one of the listed `site_ids` are
                  accepted — others are silently filtered out.
              equipment_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Equipment required to run this appointment type.
              room_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: |
                  Rooms where this appointment type can be held. Filtered to
                  rooms belonging to one of the listed `site_ids`.
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Category IDs the appointment type belongs to. Used for shopfront grouping.
              tag_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Free-form tag IDs for filtering and reporting.
              durations:
                type: array
                description: |
                  Available durations in minutes. The customer picks one when
                  booking; the duration then determines the price (via price
                  rules) and the time slot allocated.
                items:
                  type: integer
                  minimum: 1
                example:
                  - 30
                  - 60
                  - 90
              start_time_interval:
                type: integer
                minimum: 1
                description: |
                  The granularity (in minutes) at which start times are offered.
                  `15` means slots are offered at :00, :15, :30, :45.
                example: 15
              end_buffer:
                type: integer
                nullable: true
                minimum: 0
                description: |
                  Minutes of buffer time added after the appointment ends.
                  Useful for clean-up, resets, or practitioner breaks. The
                  calendar slot is reserved for `duration + end_buffer`.
                example: 15
              offered_online:
                type: boolean
                description: |
                  When true, the appointment type is bookable via the public
                  shopfront. When false, it's bookable only via the admin UI.
                  Defaults to false.
              private:
                type: boolean
                description: When true, only customers with the direct link can book this appointment type.
              visibility:
                type: string
                description: |
                  Visibility override. When set, controls who can see this
                  offering in the shopfront beyond the `offered_online`/`private`
                  defaults.
                enum:
                  - public
                  - hidden
                  - members_only
              customers_only:
                type: boolean
                description: When true, only registered customers (not guests) can book.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: |
                  Membership type IDs whose members are allowed to book. Only
                  relevant when `members_only=true`. Membership types from outside
                  the site's brand are silently filtered out.
              membership_booking_windows_enabled:
                type: boolean
                description: |
                  When true, members can book further in advance than the standard
                  window. The exact extra advance period per membership type is
                  defined in `membership_booking_windows`.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-booking-window overrides.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              min_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Minimum number of guests for a single booking.
                example: 1
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum number of guests for a single booking. If greater than
                  1, `shop_practitioner_selection` is forced to null (multi-guest
                  bookings don't support per-guest practitioner choice).
                example: 2
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers can
                  book. e.g. `P30D` = 30 days, `P1Y` = 1 year. Null means
                  unbounded.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how soon before the appointment a
                  customer can book. e.g. `PT2H` = at least 2 hours' notice.
                example: PT2H
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: |
                  Whether and when customers can cancel a booking themselves.
                  `allowed` = always. `if_unpaid` = only if no payment has been
                  taken. `disallowed` = never (admin only).
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the appointment start during which
                  cancellation is no longer permitted. e.g. `PT24H` = no
                  cancellation in the last 24 hours.
                example: PT24H
              customer_reschedule_permitted:
                description: Whether customers can reschedule an appointment of this type themselves.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the appointment start during which
                  rescheduling is no longer permitted. e.g. `PT24H` = no
                  rescheduling in the last 24 hours.
                example: PT24H
              allocate_multi_capacity_rooms:
                type: boolean
                description: |
                  When true, this appointment type can be assigned to rooms with
                  multi-guest capacity. Otherwise each booking exclusively occupies
                  the room.
              include_pricing_on_calendar:
                type: boolean
                description: Whether to surface the price alongside the offering in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of this appointment type per basket.
                example: 4
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of this appointment type per individual guest within a basket.
                example: 2
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Identifier of the revenue centre that bookings of this
                  appointment type post to. Must be a valid revenue centre for
                  every site in `site_ids`.
                example: spa-treatments
              shop_practitioner_selection:
                type: string
                nullable: true
                description: |
                  Controls whether and how the customer is asked to pick a
                  practitioner on the shopfront. `forced` = required;
                  `optional` = nice-to-have; `disabled` = practitioner is
                  auto-assigned. Forced to null when `max_guests > 1`.
                enum:
                  - forced
                  - optional
                  - disabled
              contraindications:
                type: array
                description: |
                  Health declarations to surface before booking is allowed. Each
                  entry pairs a `condition` (e.g. pregnant, recent surgery) with
                  an `indication` (cannot-book / requires-disclaimer / etc.).
                items:
                  $ref: '#/components/schemas/Contraindication'
              availability_rules:
                type: array
                description: |
                  Per-day availability rules for when this appointment type can
                  be booked. See `AvailabilityRule` schema for shape.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              upsell_offerings:
                type: array
                description: Other offerings to upsell on the booking confirmation page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Other offerings to cross-sell during the booking flow.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Retail products to display as related to this appointment type.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` to use as the cover image.
                example: 5f1234567890abcdef123456
              meta:
                type: object
                title: AppointmentTypeMetaBody
                additionalProperties: false
                description: SEO metadata for the public shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
            required:
              - name
              - site_ids
    UpdateAppointmentType:
      description: |
        Partial update for an existing `AppointmentType`. Every field is
        optional; send only the ones you want to change. Most fields mirror
        `CreateAppointmentType`; note that `site_ids` and `organisation_id`
        are fixed at create time and cannot be changed here.
      required: true
      content:
        application/json:
          schema:
            title: UpdateAppointmentType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name. Plain text only — HTML tags are rejected.
                example: Aromatherapy Massage 60 minutes
              description:
                type: string
                nullable: true
                description: Long-form description shown to customers. Markdown rendered.
                example: |
                  A relaxing aromatherapy massage using a blend of essential oils
                  tailored to your needs.
              product_code:
                type: string
                nullable: true
                description: External POS/PMS product code.
                example: MASSAGE-AROMA-60
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations.
                example: ext-aroma-60
              price:
                type: integer
                nullable: true
                description: |
                  Base price in the smallest currency unit (e.g. pence/cents).
                  Most appointments instead use price rules; this field is a
                  flat override for the simplest case.
                example: 9500
              currency:
                $ref: '#/components/schemas/properties_currency'
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this appointment type, in the
                  smallest currency unit (e.g. pence/cents). Pass `null`
                  to clear a previously-set standard price.
                example: 5000
              practitioner_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Practitioners who can perform this type. Filtered to those at the appointment type's site.
              equipment_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: |
                  Equipment IDs required to run this appointment type.
                  Bookings are only offered for time slots where at least
                  one of each listed equipment is available.
              room_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Rooms where the type can be held. Filtered to the appointment type's site.
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Category IDs for shopfront grouping.
              tag_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Tag IDs for filtering and reporting.
              durations:
                type: array
                description: Available durations in minutes.
                items:
                  type: integer
                  minimum: 1
              start_time_interval:
                type: integer
                minimum: 1
                description: Granularity (in minutes) at which start times are offered.
                example: 15
              end_buffer:
                type: integer
                nullable: true
                minimum: 0
                description: Buffer minutes added after the appointment ends.
                example: 15
              offered_online:
                type: boolean
                description: Whether bookable via the public shopfront.
              private:
                type: boolean
                description: When true, only customers with the direct link can book.
              visibility:
                type: string
                description: |
                  Visibility override that determines who sees this offering
                  on the shopfront. `public` shows it to everyone; `hidden`
                  keeps it out of search and browse (still bookable by
                  direct link); `members_only` restricts to authenticated
                  members of permitted membership types.
                enum:
                  - public
                  - hidden
                  - members_only
              customers_only:
                type: boolean
                description: Restrict booking to registered customers.
              members_only:
                type: boolean
                description: Restrict booking to permitted membership-type holders.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: Membership types whose members can book when `members_only=true`.
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to apply per-membership-type advance-booking windows.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-window overrides.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              min_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Minimum guests per booking.
                example: 1
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum guests per booking. When > 1,
                  `shop_practitioner_selection` is forced to null server-side.
                example: 2
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 max-advance booking duration.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 min-advance booking duration.
                example: PT2H
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: Customer self-cancellation policy.
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which cancellation is locked.
                example: PT24H
              customer_reschedule_permitted:
                description: Updated self-reschedule policy for this appointment type.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which rescheduling is locked.
                example: PT24H
              allocate_multi_capacity_rooms:
                type: boolean
                description: Whether multi-capacity rooms can host this type.
              include_pricing_on_calendar:
                type: boolean
                description: Surface prices in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Max of this type per basket.
                example: 4
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Max of this type per guest per basket.
                example: 2
              revenue_centre:
                type: string
                nullable: true
                description: Revenue centre to post bookings to. Must be valid for the appointment type's site.
                example: spa-treatments
              shop_practitioner_selection:
                type: string
                nullable: true
                description: Shopfront practitioner-selection mode. Forced to null when `max_guests > 1`.
                enum:
                  - forced
                  - optional
                  - disabled
              contraindications:
                type: array
                description: Health-declaration prompts.
                items:
                  $ref: '#/components/schemas/Contraindication'
              availability_rules:
                type: array
                description: Per-day availability rules.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              upsell_offerings:
                type: array
                description: Upsell candidates at booking confirmation.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Cross-sell candidates during booking.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: |
                  Retail product `OfferingIdentifier`s to surface as related
                  items on the appointment type's shopfront page. Used to
                  cross-promote bottles of lotion, gift cards, etc. against
                  the relevant treatment.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` for the cover image.
                example: 5f1234567890abcdef123456
              meta:
                type: object
                title: UpdateAppointmentTypeMeta
                additionalProperties: false
                description: SEO metadata for the shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
    CopyAppointmentType:
      description: |
        Body for copying an `AppointmentType`. `name` is required so the new
        copy is distinguishable from the source; everything else is optional
        and overrides the corresponding field on the new copy. Fields not
        listed (e.g. `end_buffer`, `start_time_interval`, `image_id`) are
        inherited from the source unchanged.
      required: true
      content:
        application/json:
          schema:
            title: CopyAppointmentType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the new copy. Required so the copy is distinguishable from the source.
                example: Aromatherapy Massage 90 minutes
              external_id:
                type: string
                nullable: true
                description: |
                  Override external identifier on the copy. Defaults to null so
                  integrations don't accidentally see two offerings with the same
                  external id.
                example: ext-aroma-90
              price:
                type: integer
                nullable: true
                description: Base price in the smallest currency unit.
                example: 12500
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  Override the standard price on the copy, in the smallest
                  currency unit (e.g. pence/cents). Defaults to the
                  source's standard price when omitted.
                example: 12500
              currency:
                $ref: '#/components/schemas/properties_currency'
              description:
                type: string
                nullable: true
                description: |
                  Override the customer-facing long-form description. Defaults to
                  the source's description when omitted. Markdown rendered.
                example: |
                  An extended 90-minute aromatherapy massage with a focus on deep
                  relaxation and tension release.
              organisation_id:
                type: string
                format: uuid
                description: Override organisation; defaults to the source's.
              practitioner_ids:
                type: array
                description: |
                  Override the practitioner allowlist on the copy. Filtered to
                  practitioners at the appointment type's site; defaults to the
                  source's list.
                items:
                  type: string
                  format: object-id
              equipment_ids:
                type: array
                description: |
                  Override the equipment requirement. Defaults to the source's
                  equipment list.
                items:
                  type: string
                  format: object-id
              room_ids:
                type: array
                description: |
                  Override the rooms where the copy can be held. Filtered to the
                  appointment type's site.
                items:
                  type: string
                  format: object-id
              category_ids:
                type: array
                description: Override the shopfront category memberships on the copy.
                items:
                  type: string
                  format: object-id
              tag_ids:
                type: array
                description: Override the reporting/filtering tags on the copy.
                items:
                  type: string
                  format: object-id
              durations:
                type: array
                description: Override the available durations (in minutes) on the copy.
                items:
                  type: integer
                  minimum: 1
              start_time_interval:
                type: integer
                minimum: 1
                description: |
                  Override the start-time granularity (in minutes) on the copy.
                  `15` means slots are offered at :00, :15, :30, :45.
                example: 15
              offered_online:
                type: boolean
                description: Whether the copy is bookable via the public shopfront. Defaults to the source's value.
              private:
                type: boolean
                description: When true, only customers with the direct link can book the copy.
              visibility:
                type: string
                description: Visibility override on the copy. Same semantics as on the source.
                enum:
                  - public
                  - hidden
                  - members_only
              customers_only:
                type: boolean
                description: When true, only registered customers (not guests) can book the copy.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book the copy.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership types whose members can book the copy when
                  `members_only=true`.
                items:
                  type: string
                  format: uuid
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to apply per-membership-type advance-booking windows on the copy.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-window overrides on the copy.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers can
                  book the copy. e.g. `P30D` = 30 days.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how soon before the appointment
                  start a customer can book the copy. e.g. `PT2H` = at least 2
                  hours' notice.
                example: PT2H
              allocate_multi_capacity_rooms:
                type: boolean
                description: |
                  When true, the copy can be assigned to rooms with multi-guest
                  capacity; otherwise each booking exclusively occupies the room.
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: |
                  Customer self-cancellation policy on the copy. `allowed` =
                  always; `if_unpaid` = only if no payment has been taken;
                  `disallowed` = never.
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the appointment start during which
                  cancellation is no longer permitted on the copy.
                example: PT24H
              customer_reschedule_permitted:
                description: Self-reschedule policy applied to the copied appointment type.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the appointment start during which
                  rescheduling is no longer permitted on the copy.
                example: PT24H
              include_pricing_on_calendar:
                type: boolean
                description: Whether to surface the price alongside the offering in calendar views on the copy.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of the copy per basket.
                example: 4
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of the copy per individual guest within a basket.
                example: 2
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Revenue centre identifier that bookings of the copy post to.
                  Must be a valid revenue centre for the appointment type's site.
                example: spa-treatments
              shop_practitioner_selection:
                type: string
                nullable: true
                description: |
                  Shopfront practitioner-selection mode on the copy. Forced to
                  null when `max_guests > 1`.
                enum:
                  - forced
                  - optional
                  - disabled
              contraindications:
                type: array
                description: Override the contraindication prompts on the copy.
                items:
                  $ref: '#/components/schemas/Contraindication'
              availability_rules:
                type: array
                description: Override the per-day availability rules on the copy.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              upsell_offerings:
                type: array
                description: Override the upsell candidates surfaced at booking confirmation on the copy.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Override the cross-sell candidates surfaced during the booking flow on the copy.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Override the related retail products surfaced on the copy's shopfront page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              meta:
                type: object
                title: CopyAppointmentTypeMeta
                additionalProperties: false
                description: SEO metadata for the copy's shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
            required:
              - name
    CreateAppointmentTypeAvailabilityRule:
      description: |
        Body for creating a new `AvailabilityRule` on an `AppointmentType`.
        Only `is_available` is required; the remaining fields filter when
        the rule applies.
      required: true
      content:
        application/json:
          schema:
            title: CreateAppointmentTypeAvailabilityRule
            allOf:
              - $ref: '#/components/schemas/schema'
    UpdateAppointmentTypeAvailabilityRule:
      description: |
        Body for updating an existing `AvailabilityRule`. `is_available` is
        required (the same validator runs on create + update server-side);
        every other field is optional and overrides the current value when
        sent.
      required: true
      content:
        application/json:
          schema:
            title: UpdateAppointmentTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: Whether the window is bookable. `false` rules override `true` rules.
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Daily start time in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: Daily end time in `HH:MM`.
                example: '18:00'
              min_duration:
                type: integer
                minimum: 1
                nullable: true
                description: Match only for durations ≥ this many minutes.
                example: 30
              max_duration:
                type: integer
                minimum: 1
                nullable: true
                description: Match only for durations ≤ this many minutes.
                example: 120
              weekdays:
                type: array
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
            required:
              - is_available
    CreateAppointmentTypePriceRule:
      description: |
        Body for creating a new `PriceRule` on an `AppointmentType`. Only
        `price` is strictly required; all other fields are filters that
        restrict when the rule applies. With no filters, the rule applies to
        every booking of this appointment type (useful as a fallback default).
      required: true
      content:
        application/json:
          schema:
            title: CreateAppointmentTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: |
                  Price in the smallest currency unit (e.g. pence, cents).
                  `4800` means £48.00 in a GBP-denominated site.
                example: 4800
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date this rule applies (inclusive). Defaults to today
                  in the site's timezone if omitted.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date this rule applies (inclusive). When omitted, the
                  rule has no end date.
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: |
                  Start of the time-of-day window in 24-hour `HH:MM` format.
                  When `time_to` is set, must be earlier than `time_to` (the
                  rule does not wrap past midnight).
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: |
                  End of the time-of-day window in 24-hour `HH:MM` format.
                  Must be later than `time_from` if both are set.
                example: '18:00'
              duration:
                type: integer
                minimum: 1
                description: |
                  Match this rule only when the customer picks the given
                  appointment duration (in minutes). Omit to apply the rule
                  regardless of duration.
                example: 60
              weekdays:
                type: array
                description: |
                  Days of the week this rule applies on. Empty / omitted means
                  every day.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - saturday
                  - sunday
            required:
              - price
    UpdateAppointmentTypePriceRule:
      description: |
        Body for updating an existing `PriceRule`. Every field is optional;
        only fields you send are written. Omitted fields keep their current
        values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateAppointmentTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: Price in the smallest currency unit.
                example: 4800
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Start of the time-of-day window in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: End of the time-of-day window in `HH:MM`.
                example: '18:00'
              duration:
                type: integer
                minimum: 1
                description: Match only this duration in minutes.
                example: 60
              weekdays:
                type: array
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
    UpdateAppointmentTypeLocaleStrings:
      description: Update locale strings for an AppointmentType
      required: true
      content:
        application/json:
          schema:
            title: UpdateAppointmentTypeLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this appointment type in the given locale.
                example: Deep Tissue Massage
              description:
                type: string
                nullable: true
                description: The localised description for this appointment type in the given locale.
                example: A therapeutic massage targeting deep muscle layers.
              meta_title:
                type: string
                nullable: true
                description: The localised meta title for this appointment type in the given locale.
                example: Deep Tissue Massage | Book Online
              meta_description:
                type: string
                nullable: true
                description: The localised meta description for this appointment type in the given locale.
                example: Book our deep tissue massage to relieve muscle tension and improve circulation.
    CreateAreaBookingType:
      description: |
        Body for creating a new `AreaBookingType`. `name`,
        `start_time_interval`, `duration_interval`, `min_duration` and
        `max_duration` are required; everything else has a sensible default
        or `null`-equivalent. See `AreaBookingType` in `schemas.yml` for the
        full field list and their semantics — this body accepts the same
        write-able fields. The created type is bound to the site referenced
        in the `Trybe-Site-Id` header.
      required: true
      content:
        application/json:
          schema:
            title: CreateAreaBookingType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the area booking type. Visible to customers in
                  the booking flow and to staff in the admin UI. Plain text only —
                  HTML tags are rejected at validation time.
                example: Poolside Cabana
              description:
                type: string
                description: |
                  Long-form description shown to customers when they're selecting
                  the area. Markdown is rendered.
                example: |
                  A private four-person cabana steps from the main pool. Includes
                  dedicated wait service, fresh towels, and a chilled fruit
                  platter on arrival.
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map this area booking type to an
                  external POS or PMS catalog. Free-form string; uniqueness is
                  not enforced server-side.
                example: CABANA-POOL-4P
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this offering. Free-form.
                example: ext-cabana-pool-4p
              currency:
                $ref: '#/components/schemas/properties_currency'
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this area booking type, in the
                  smallest currency unit (e.g. pence/cents). Optional at
                  create time — offerings can be created without a
                  standard price and have one configured later.
                example: 5000
              start_time_interval:
                type: integer
                minimum: 1
                description: |
                  The granularity (in minutes) at which start times are offered.
                  `30` means slots are offered on the hour and half-hour.
                example: 30
              duration_interval:
                type: integer
                minimum: 1
                description: |
                  The granularity (in minutes) at which the customer can extend
                  their booking beyond `min_duration`, up to `max_duration`.
                  `60` means durations are picked in one-hour steps.
                example: 60
              min_duration:
                type: integer
                minimum: 1
                description: |
                  Minimum bookable duration in minutes. Customers cannot pick
                  a duration shorter than this.
                example: 120
              max_duration:
                type: integer
                minimum: 1
                description: |
                  Maximum bookable duration in minutes. Customers cannot pick
                  a duration longer than this.
                example: 480
              end_buffer:
                type: integer
                nullable: true
                minimum: 0
                description: |
                  Minutes of buffer time added after the booking ends.
                  Useful for reset, cleaning, or staff handover. The
                  calendar slot is reserved for `duration + end_buffer`.
                example: 15
              max_baskets:
                type: integer
                minimum: 0
                description: |
                  Maximum number of concurrent baskets (distinct customer
                  bookings) that can hold the same time slot. `0` is treated
                  as no parallel allowance — only one booking holds the area
                  at any time. Use higher values when the area accepts
                  multiple parties simultaneously (e.g. shared sun-loungers).
                example: 1
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum number of guests a single booking of this area can
                  cover. Used to surface a guest-count selector in the booking
                  flow.
                example: 4
              area_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: |
                  `BookableArea` IDs this booking type maps to. Filtered to
                  areas belonging to the site referenced in the
                  `Trybe-Site-Id` header; areas outside the site are silently
                  filtered out.
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Category IDs the area booking type belongs to. Used for shopfront grouping.
              offered_online:
                type: boolean
                description: |
                  When true, the area booking type is bookable via the public
                  shopfront. When false, it's bookable only via the admin UI.
                  Defaults to false.
              private:
                type: boolean
                description: When true, only customers with the direct link can book this area booking type.
              visibility:
                type: string
                description: |
                  Visibility override. When set, controls who can see this
                  offering in the shopfront beyond the `offered_online`/`private`
                  defaults.
                enum:
                  - public
                  - hidden
                  - members_only
              customers_only:
                type: boolean
                description: When true, only registered customers (not guests) can book.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: |
                  Membership type IDs whose members are allowed to book. Only
                  relevant when `members_only=true`. Membership types from outside
                  the site's brand are silently filtered out.
              membership_booking_windows_enabled:
                type: boolean
                description: |
                  When true, members can book further in advance than the standard
                  window. The exact extra advance period per membership type is
                  defined in `membership_booking_windows`.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-booking-window overrides.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers can
                  book. e.g. `P30D` = 30 days, `P1Y` = 1 year. Null means
                  unbounded.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how soon before the booking start
                  time a customer can place a booking. e.g. `PT2H` = at least 2
                  hours' notice.
                example: PT2H
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: |
                  Whether and when customers can cancel a booking themselves.
                  `allowed` = always. `if_unpaid` = only if no payment has been
                  taken. `disallowed` = never (admin only).
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the booking start during which
                  cancellation is no longer permitted. e.g. `PT24H` = no
                  cancellation in the last 24 hours.
                example: PT24H
              customer_reschedule_permitted:
                description: Whether customers can reschedule an area booking of this type themselves.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the booking start during which
                  rescheduling is no longer permitted. e.g. `PT24H` = no
                  rescheduling in the last 24 hours.
                example: PT24H
              include_pricing_on_calendar:
                type: boolean
                description: Whether to surface the price alongside the offering in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of this area booking type per basket.
                example: 4
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of this area booking type per individual guest within a basket.
                example: 2
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Identifier of the revenue centre that bookings of this area
                  booking type post to. Must be a valid revenue centre for the
                  site.
                example: pool-cabanas
              upsell_offerings:
                type: array
                description: Other offerings to upsell on the booking confirmation page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Other offerings to cross-sell during the booking flow.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Retail products to display as related to this area booking type.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
            required:
              - name
              - start_time_interval
              - duration_interval
              - min_duration
              - max_duration
    UpdateAreaBookingType:
      description: |
        Partial update for an existing `AreaBookingType`. Every field is
        optional; send only the ones you want to change. Most fields mirror
        `CreateAreaBookingType`; note that the site this type belongs to is
        fixed at create time and cannot be changed here.
      required: true
      content:
        application/json:
          schema:
            title: UpdateAreaBookingType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name. Plain text only — HTML tags are rejected.
                example: Poolside Cabana
              description:
                type: string
                nullable: true
                description: Long-form description shown to customers. Markdown rendered.
                example: |
                  A private four-person cabana steps from the main pool with
                  dedicated wait service.
              product_code:
                type: string
                nullable: true
                description: External POS/PMS product code.
                example: CABANA-POOL-4P
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations.
                example: ext-cabana-pool-4p
              currency:
                $ref: '#/components/schemas/properties_currency'
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this area booking type, in the
                  smallest currency unit (e.g. pence/cents). Pass `null`
                  to clear a previously-set standard price.
                example: 5000
              start_time_interval:
                type: integer
                minimum: 1
                description: Granularity (in minutes) at which start times are offered.
                example: 30
              duration_interval:
                type: integer
                minimum: 1
                description: Granularity (in minutes) at which the customer can extend the booking between `min_duration` and `max_duration`.
                example: 60
              min_duration:
                type: integer
                minimum: 1
                description: Minimum bookable duration in minutes.
                example: 120
              max_duration:
                type: integer
                minimum: 1
                description: Maximum bookable duration in minutes.
                example: 480
              end_buffer:
                type: integer
                nullable: true
                minimum: 0
                description: Buffer minutes added after the booking ends.
                example: 15
              max_baskets:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum number of concurrent baskets that can hold the same
                  time slot. On update this is nullable (set to `null` to clear
                  any previously configured cap).
                example: 1
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of guests a single booking of this area can cover.
                example: 4
              area_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: |
                  `BookableArea` IDs this booking type maps to. Filtered to
                  areas belonging to the area booking type's site.
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Category IDs for shopfront grouping.
              offered_online:
                type: boolean
                description: Whether bookable via the public shopfront.
              private:
                type: boolean
                description: When true, only customers with the direct link can book.
              visibility:
                type: string
                description: |
                  Visibility override that determines who sees this offering
                  on the shopfront. `public` shows it to everyone; `hidden`
                  keeps it out of search and browse (still bookable by
                  direct link); `members_only` restricts to authenticated
                  members of permitted membership types.
                enum:
                  - public
                  - hidden
                  - members_only
              customers_only:
                type: boolean
                description: Restrict booking to registered customers.
              members_only:
                type: boolean
                description: Restrict booking to permitted membership-type holders.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: Membership types whose members can book when `members_only=true`.
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to apply per-membership-type advance-booking windows.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-window overrides.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 max-advance booking duration.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 min-advance booking duration.
                example: PT2H
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: Customer self-cancellation policy.
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which cancellation is locked.
                example: PT24H
              customer_reschedule_permitted:
                description: Updated self-reschedule policy for this area booking type.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which rescheduling is locked.
                example: PT24H
              include_pricing_on_calendar:
                type: boolean
                description: Surface prices in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Max of this type per basket.
                example: 4
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Max of this type per guest per basket.
                example: 2
              revenue_centre:
                type: string
                nullable: true
                description: Revenue centre to post bookings to. Must be valid for the area booking type's site.
                example: pool-cabanas
              upsell_offerings:
                type: array
                description: Upsell candidates at booking confirmation.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Cross-sell candidates during booking.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: |
                  Retail product `OfferingIdentifier`s to surface as related
                  items on the area booking type's shopfront page. Used to
                  cross-promote add-ons (towels, bottles of sunscreen, gift
                  cards) against the area being booked.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` for the cover image.
                example: 5f1234567890abcdef123456
              meta:
                type: object
                title: UpdateAreaBookingTypeMeta
                additionalProperties: false
                description: SEO metadata for the shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
    CreateAreaBookingTypeAvailabilityRule:
      description: |
        Body for creating a new `AvailabilityRule` on an `AreaBookingType`.
        Only `is_available` is required; the remaining fields filter when
        the rule applies.
      required: true
      content:
        application/json:
          schema:
            title: CreateAreaBookingTypeAvailabilityRule
            allOf:
              - $ref: '#/components/schemas/application~1json-schema'
    UpdateAreaBookingTypeAvailabilityRule:
      description: |
        Body for updating an existing `AvailabilityRule`. `is_available` is
        required (the same validator runs on create + update server-side);
        every other field is optional and overrides the current value when
        sent.
      required: true
      content:
        application/json:
          schema:
            title: UpdateAreaBookingTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: Whether the window is bookable. `false` rules override `true` rules.
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Daily start time in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: Daily end time in `HH:MM`.
                example: '18:00'
              min_duration:
                type: integer
                minimum: 1
                description: Match only for durations ≥ this many minutes.
                example: 60
              max_duration:
                type: integer
                minimum: 1
                description: Match only for durations ≤ this many minutes.
                example: 480
              weekdays:
                type: array
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
            required:
              - is_available
    CopyAreaBookingType:
      description: |
        Body for copying an `AreaBookingType`. `name` is required so the new
        copy is distinguishable from the source; everything else is optional
        and overrides the corresponding field on the new copy. Fields not
        listed (e.g. `availability_rules`, `price_rules`, `image`) are inherited
        from the source unchanged.
      required: true
      content:
        application/json:
          schema:
            title: CopyAreaBookingType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the new copy. Required so the copy is distinguishable from the source.
                example: Poolside Cabana — Premium
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  Override the standard price on the copy, in the smallest
                  currency unit (e.g. pence/cents). Defaults to the
                  source's standard price when omitted.
                example: 5000
              currency:
                $ref: '#/components/schemas/properties_currency'
              description:
                type: string
                description: |
                  Override the customer-facing long-form description. Defaults to
                  the source's description when omitted. Markdown rendered.
                example: |
                  An upgraded four-person cabana with premium fittings and an
                  extended drinks package.
              product_code:
                type: string
                nullable: true
                description: External POS/PMS product code on the copy.
                example: CABANA-POOL-4P-PREM
              external_id:
                type: string
                nullable: true
                description: |
                  Override external identifier on the copy. Defaults to null so
                  integrations don't accidentally see two offerings with the same
                  external id.
                example: ext-cabana-pool-4p-prem
              start_time_interval:
                type: integer
                minimum: 1
                description: |
                  Override the start-time granularity (in minutes) on the copy.
                  `30` means slots are offered on the hour and half-hour.
                example: 30
              duration_interval:
                type: integer
                minimum: 1
                description: Override the duration step (in minutes) on the copy.
                example: 60
              min_duration:
                type: integer
                minimum: 1
                description: Override the minimum bookable duration (in minutes) on the copy.
                example: 120
              max_duration:
                type: integer
                minimum: 1
                description: Override the maximum bookable duration (in minutes) on the copy.
                example: 480
              end_buffer:
                type: integer
                nullable: true
                minimum: 0
                description: Override the buffer minutes after each booking on the copy.
                example: 15
              max_baskets:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Override the maximum number of concurrent baskets the copy
                  accepts on the same time slot.
                example: 1
              area_ids:
                type: array
                description: |
                  Override the bookable areas the copy maps to. Filtered to
                  `BookableArea`s belonging to the source's site.
                items:
                  type: string
                  format: object-id
              category_ids:
                type: array
                description: Override the shopfront category memberships on the copy.
                items:
                  type: string
                  format: object-id
              offered_online:
                type: boolean
                description: Whether the copy is bookable via the public shopfront. Defaults to the source's value.
              private:
                type: boolean
                description: When true, only customers with the direct link can book the copy.
              visibility:
                type: string
                description: Visibility override on the copy. Same semantics as on the source.
                enum:
                  - public
                  - hidden
                  - members_only
              customers_only:
                type: boolean
                description: When true, only registered customers (not guests) can book the copy.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book the copy.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership types whose members can book the copy when
                  `members_only=true`.
                items:
                  type: string
                  format: uuid
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to apply per-membership-type advance-booking windows on the copy.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-window overrides on the copy.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers can
                  book the copy. e.g. `P30D` = 30 days.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how soon before the booking start
                  time a customer can book the copy. e.g. `PT2H` = at least 2
                  hours' notice.
                example: PT2H
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: |
                  Customer self-cancellation policy on the copy. `allowed` =
                  always; `if_unpaid` = only if no payment has been taken;
                  `disallowed` = never.
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the booking start during which
                  cancellation is no longer permitted on the copy.
                example: PT24H
              customer_reschedule_permitted:
                description: Self-reschedule policy applied to the copied area booking type.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the booking start during which
                  rescheduling is no longer permitted on the copy.
                example: PT24H
              include_pricing_on_calendar:
                type: boolean
                description: Whether to surface the price alongside the offering in calendar views on the copy.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of the copy per basket.
                example: 4
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of the copy per individual guest within a basket.
                example: 2
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Revenue centre identifier that bookings of the copy post to.
                  Must be a valid revenue centre for the area booking type's
                  site.
                example: pool-cabanas
              upsell_offerings:
                type: array
                description: Override the upsell candidates surfaced at booking confirmation on the copy.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Override the cross-sell candidates surfaced during the booking flow on the copy.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Override the related retail products surfaced on the copy's shopfront page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              meta:
                type: object
                title: CopyAreaBookingTypeMeta
                additionalProperties: false
                description: SEO metadata for the copy's shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
            required:
              - name
    CreateAreaBookingTypePriceRule:
      description: |
        Body for creating a new price rule on an `AreaBookingType`. Both
        `price` and `max_duration` are required; all other fields are filters
        that restrict when the rule applies. With no filters, the rule applies
        to every booking of this area booking type whose duration is ≤ the
        rule's `max_duration` (useful as a fallback default).
      required: true
      content:
        application/json:
          schema:
            title: CreateAreaBookingTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                description: |
                  Price in the smallest currency unit (e.g. pence, cents).
                  `12000` means £120.00 in a GBP-denominated site.
                example: 12000
              max_duration:
                type: integer
                minimum: 1
                description: |
                  Apply this rule to bookings up to this many minutes long.
                  For an area booking, this is typically how the day-rate vs
                  half-day rate split is expressed.
                example: 240
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date this rule applies (inclusive). Defaults to today
                  in the site's timezone if omitted.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date this rule applies (inclusive). When omitted, the
                  rule has no end date.
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: |
                  Start of the time-of-day window in 24-hour `HH:MM` format.
                  When `time_to` is set, must be earlier than `time_to` (the
                  rule does not wrap past midnight).
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: |
                  End of the time-of-day window in 24-hour `HH:MM` format.
                  Must be later than `time_from` if both are set.
                example: '18:00'
              weekdays:
                type: array
                nullable: true
                description: |
                  Days of the week this rule applies on. Empty / omitted means
                  every day.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - saturday
                  - sunday
            required:
              - price
              - max_duration
    UpdateAreaBookingTypePriceRule:
      description: |
        Body for updating an existing price rule. Every field is optional;
        only fields you send are written. Omitted fields keep their current
        values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateAreaBookingTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                description: Price in the smallest currency unit.
                example: 12000
              max_duration:
                type: integer
                minimum: 1
                description: Apply this rule to bookings up to this many minutes long.
                example: 240
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Start of the time-of-day window in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: End of the time-of-day window in `HH:MM`.
                example: '18:00'
              weekdays:
                type: array
                nullable: true
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
    UpdateAreaBookingTypeLocaleStrings:
      description: Update locale strings for an AreaBookingType
      required: true
      content:
        application/json:
          schema:
            title: UpdateAreaBookingTypeLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this area booking type in the given locale.
                example: Tennis Court
              description:
                type: string
                nullable: true
                description: The localised description for this area booking type in the given locale.
                example: An outdoor tennis court available for hourly booking.
              meta_title:
                type: string
                nullable: true
                description: The localised meta title for this area booking type in the given locale.
                example: Tennis Court | Book Online
              meta_description:
                type: string
                nullable: true
                description: The localised meta description for this area booking type in the given locale.
                example: Book a tennis court session and enjoy our well-maintained outdoor facilities.
    CreateBasket:
      required: true
      content:
        application/json:
          schema:
            title: CreateBasket
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the `Site` the basket belongs to. The site determines
                  currency, tax configuration, payment processors, and which
                  offerings are bookable.
                example: 9c3ad1e2-2d1b-4f4f-9e07-6d6c4f3a2b1a
              customer_id:
                type: string
                format: uuid
                description: |
                  Optionally pre-link an existing `Customer` to the basket.
                  Ignored unless the customer belongs to the same brand as
                  the site. If the request is authenticated as a customer,
                  the authenticated customer takes precedence.
                example: 5e1e3f6c-2a44-4f6e-8c61-9c1f7d2e1c11
            required:
              - site_id
    UpdateBasket:
      required: true
      content:
        application/json:
          schema:
            title: UpdateBasket
            type: object
            additionalProperties: false
            properties:
              special_requests:
                type: string
                description: |
                  Free-text notes captured against the basket during
                  checkout. Surfaced to operations staff alongside the
                  resulting `Order`.
                example: Window table if possible, allergic to shellfish.
    CreateBasketCoupon:
      required: true
      content:
        application/json:
          schema:
            title: CreateBasketCoupon
            type: object
            additionalProperties: false
            properties:
              code:
                type: string
                description: |
                  The customer-visible coupon code to redeem. Matched
                  case-insensitively against issued `CouponCode` records
                  for the basket's site.
                example: WELCOME20
            required:
              - code
    SetBasketCustomer:
      required: true
      content:
        application/json:
          schema:
            title: SetBasketCustomer
            type: object
            additionalProperties: false
            properties:
              email:
                type: string
                description: |
                  Customer email address. **Required** for guest
                  checkout. Used to look up existing customers within the
                  site's brand before creating a new record.
                example: avery.lin@example.com
              first_name:
                type: string
                description: |
                  Customer's given name. **Required** for guest checkout.
                example: Avery
              last_name:
                type: string
                description: |
                  Customer's family name. **Required** for guest
                  checkout.
                example: Lin
              phone:
                type: string
                nullable: true
                description: |
                  Customer's phone number. Required when the
                  authenticated customer doesn't already have one on
                  file; optional otherwise. Accepted in any format
                  parseable against `phone_country` or the site's
                  country code; persisted as E.164.
                example: '+447700900100'
              phone_country:
                type: string
                nullable: true
                description: |
                  Two-letter ISO country code used to interpret an
                  unprefixed `phone`. Defaults to the site's country code
                  when omitted.
                example: GB
              marketing_preferences:
                type: array
                description: |
                  IDs of marketing preferences the customer has opted in
                  to. Only honoured when creating a brand-new customer.
                items:
                  type: string
                  format: object-id
                example:
                  - 5f5555555555555555555555
    CreateBasketCustomerCredit:
      required: true
      content:
        application/json:
          schema:
            title: CreateBasketCustomerCredit
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                format: object-id
                description: |
                  ID of the `CustomerCredit` to redeem against the
                  basket. Must belong to the customer attached to the
                  basket and have a remaining balance.
                example: 5f6666666666666666666666
            required:
              - id
    UpdateBasketItem:
      required: true
      content:
        application/json:
          schema:
            title: UpdateBasketItem
            type: object
            additionalProperties: false
            properties:
              date:
                type: string
                format: date
                nullable: true
                description: |
                  Booking date for the item. Required for scheduled
                  offerings (appointments, area bookings, sessions).
                example: '2026-07-14'
              time:
                type: string
                description: |
                  Booking start time for the item, formatted as `HH:mm`.
                  For ranged bookings such as area bookings, pair with
                  `end_time` or `duration` to express the slot.
                example: '14:30'
              start_time:
                type: string
                description: |
                  Alternative start time for ranged bookings. Formatted
                  as `HH:mm`.
                example: '14:30'
              end_time:
                type: string
                description: |
                  End time for ranged bookings. Formatted as `HH:mm`.
                example: '16:00'
              duration:
                type: integer
                nullable: true
                description: |
                  Booking duration in minutes. Must be greater than zero
                  when supplied; allowed durations are constrained by the
                  offering's settings.
                example: 60
              quantity:
                type: integer
                description: |
                  Number of units of this item. Must be greater than zero.
                  Setting `quantity` to `0` removes the line from the
                  basket instead of updating it.
                example: 2
              item_configuration:
                type: object
                additionalProperties: true
                nullable: true
                description: |
                  Offering-specific configuration for this line. The
                  accepted keys depend on the `offering_type` — for
                  example `practitioner_id`, `room_id`, `session_id`,
                  option selections, or product variants. Unknown keys
                  are ignored.
                example:
                  practitioner_id: 5f1234567890abcdef123456
                  option_selections:
                    aromatherapy_oil: lavender
    CreateBasketPackageItem:
      required: true
      content:
        application/json:
          schema:
            title: CreateBasketPackageItem
            type: object
            additionalProperties: false
            properties:
              choice_id:
                type: string
                description: |
                  ID of the choice within the parent package that this
                  child item is filling. Each `Package` defines a list of
                  choices (e.g. "Main treatment", "Lunch", "Add-on") and
                  the customer picks one `option_id` for each.
                example: 5f1111111111111111111111
              option_id:
                type: string
                description: |
                  ID of the offering option fulfilling the choice. Must
                  be one of the options defined against `choice_id`.
                example: 5f2222222222222222222222
              item_configuration:
                title: CreateBasketPackageItemConfiguration
                type: object
                additionalProperties: true
                description: |
                  Slot-specific configuration. Common keys include `time`
                  (`HH:mm`), `duration` (minutes), and `session_id`. Unknown
                  keys are ignored.
                properties:
                  time:
                    type: string
                    description: Start time for the slot, formatted as `HH:mm`.
                    example: '11:00'
                  duration:
                    type: integer
                    description: Duration of the slot in minutes.
                    example: 60
                  session_id:
                    type: string
                    format: object-id
                    description: ID of the chosen `Session`, if the option is session-based.
                    example: 5f3333333333333333333333
              guest_ids:
                type: array
                description: |
                  IDs of the guests this package item applies to. When
                  omitted the item applies to the same guests as its
                  parent basket item.
                items:
                  type: string
                  format: object-id
              time:
                deprecated: true
                type: string
                description: |
                  Legacy alternative to `item_configuration.time`. Prefer
                  passing the value inside `item_configuration`.
                example: '11:00'
              duration:
                deprecated: true
                type: integer
                description: |
                  Legacy alternative to `item_configuration.duration`.
                  Prefer passing the value inside `item_configuration`.
                example: 60
            required:
              - choice_id
              - option_id
    UpdateBasketPackageItem:
      required: true
      content:
        application/json:
          schema:
            title: UpdateBasketPackageItem
            type: object
            additionalProperties: false
            properties:
              choice_id:
                type: string
                description: ID of the package choice this child item fulfils.
                example: 5f1111111111111111111111
              option_id:
                type: string
                description: ID of the offering option selected for the choice.
                example: 5f2222222222222222222222
              time:
                type: string
                description: New start time for the slot, formatted as `HH:mm`.
                example: '12:00'
              duration:
                type: integer
                description: New duration of the slot in minutes.
                example: 90
            required:
              - choice_id
              - option_id
    CreateBasketPayment:
      required: true
      content:
        application/json:
          schema:
            title: CreateBasketPayment
            type: object
            additionalProperties: true
            properties:
              processor:
                type: string
                description: |
                  The payment processor handling this payment. `voucher`
                  and `external_voucher` redeem a voucher held on the
                  basket; `stripe` is accepted as a no-op for clients
                  that still POST after a Stripe Checkout redirect.
                enum:
                  - voucher
                  - external_voucher
                  - stripe
                example: voucher
              amount:
                type: integer
                description: |
                  Amount to charge against this payment, in the smallest
                  currency unit (e.g. pence, cents). Defaults to the
                  basket's outstanding submit amount when omitted. Must
                  not exceed the outstanding amount.
                example: 4800
              voucher_code:
                type: string
                description: |
                  For voucher processors, the voucher code to redeem.
                  Required when `processor` is `voucher` or
                  `external_voucher` and the voucher hasn't already been
                  attached via `POST /shop/basket/{basketId}/vouchers`.
                example: GIFT-9F2K-AT3X
              notes:
                type: string
                description: |
                  Optional free-text note recorded against the
                  `Payment`.
                example: Redeemed at checkout
            required:
              - processor
    SubmitBasket:
      required: false
      content:
        application/json:
          schema:
            title: SubmitBasket
            type: object
            additionalProperties: true
            description: |
              The submit endpoint accepts the same set of customer
              fields as `POST /shop/basket/{basketId}/customer`. Including
              any of `customer_id`, `email`, `first_name`, `last_name`,
              `phone`, or `marketing_preferences` causes the customer to
              be set as part of the submit, saving a round-trip for
              one-page checkouts.
            properties:
              customer_id:
                type: string
                format: uuid
                description: |
                  Existing `Customer` to attach to the basket before
                  submitting.
              email:
                type: string
                description: Email address for guest checkout.
                example: avery.lin@example.com
              first_name:
                type: string
                description: Customer's given name for guest checkout.
                example: Avery
              last_name:
                type: string
                description: Customer's family name for guest checkout.
                example: Lin
              phone:
                type: string
                description: |
                  Customer's phone number. Persisted as E.164 using
                  `phone_country` (or the site's country code) as the
                  default region.
                example: '+447700900100'
              phone_country:
                type: string
                description: |
                  Two-letter ISO country code used to interpret an
                  unprefixed `phone`.
                example: GB
              marketing_preferences:
                type: array
                items:
                  type: string
                  format: object-id
                description: |
                  IDs of marketing preferences the customer is opting in
                  to. Only honoured when creating a new customer.
    BulkUpdateBasketGuests:
      required: true
      content:
        application/json:
          schema:
            title: BulkUpdateBasketGuests
            type: object
            additionalProperties: false
            properties:
              guests:
                type: array
                description: |
                  The set of guests to upsert against the basket. Each
                  entry may identify an existing guest by `id` (in which
                  case the remaining fields patch the record) or omit
                  `id` to create a new guest.
                items:
                  title: BulkUpdateBasketGuestsGuest
                  type: object
                  additionalProperties: true
                  properties:
                    id:
                      type: string
                      format: object-id
                      description: |
                        ID of an existing `Guest` on the basket. Omit to
                        create a new guest.
                      example: 5f4444444444444444444444
                    name:
                      type: string
                      description: Guest's display name.
                      example: Avery Lin
                    customer_id:
                      type: string
                      format: uuid
                      description: |
                        Optionally link this guest to an existing
                        `Customer` record.
                    is_lead_booker:
                      type: boolean
                      description: |
                        Marks this guest as the lead booker for the
                        basket. Exactly one guest can hold this role.
    CreateBasketVoucher:
      required: true
      content:
        application/json:
          schema:
            title: CreateBasketVoucher
            type: object
            additionalProperties: false
            properties:
              code:
                type: string
                description: |
                  The customer-visible voucher code to redeem. May be a
                  Trybe-issued code or a code provisioned by an external
                  voucher integration connected to the site.
                example: GIFT-9F2K-AT3X
            required:
              - code
    CreateBookableArea:
      description: |
        Body for creating a new `BookableArea`. `name` and `capacity` are
        required; the new area is scoped to the `site_id` query parameter
        sent on the request. `description` and `zone_ids` are optional.
      required: true
      content:
        application/json:
          schema:
            title: CreateBookableArea
            allOf:
              - $ref: '#/components/schemas/content-application~1json-schema'
    UpdateBookableArea:
      description: |
        Body for updating a `BookableArea`. `name` and `capacity` are
        required by the validator (the same shape is enforced on create
        and update); `description` and `zone_ids` are optional.
      required: true
      content:
        application/json:
          schema:
            title: UpdateBookableArea
            type: object
            additionalProperties: false
            required:
              - name
              - capacity
            properties:
              name:
                type: string
                description: New display name for the bookable area.
                example: Hot Tub 1
              description:
                type: string
                nullable: true
                description: |
                  Replacement long-form description shown to customers on
                  the shopfront. Markdown is rendered. Pass null to clear.
                example: Heated 4-person hot tub with hydrotherapy jets, available year-round.
              capacity:
                type: integer
                minimum: 1
                description: |
                  New capacity. Lowering capacity doesn't cancel existing
                  bookings — they keep their slot.
                example: 4
              zone_ids:
                type: array
                description: Zones the area belongs to. Filtered to the area's site.
                items:
                  type: string
                  format: object-id
    CopyBookableArea:
      description: |
        Body for copying a `BookableArea`. `name` and `capacity` are
        required so the new copy is distinguishable from the source and
        has a valid capacity. `description` and `zone_ids` are optional.
      required: true
      content:
        application/json:
          schema:
            title: CopyBookableArea
            type: object
            additionalProperties: false
            required:
              - name
              - capacity
            properties:
              name:
                type: string
                description: Display name for the new copy.
                example: Hot Tub 2
              description:
                type: string
                description: |
                  Long-form description for the new copy, shown to customers
                  on the shopfront. Markdown is rendered. Omit to inherit
                  the source area's description.
                example: A second hot-tub bay alongside the first, set up for couples bookings.
              capacity:
                type: integer
                minimum: 1
                description: |
                  Maximum guests this area can hold concurrently. Defaults
                  to the source area's capacity when omitted. Lowering
                  capacity later does not affect existing bookings already
                  above the limit.
                example: 4
              zone_ids:
                type: array
                description: Zones the copy belongs to. Filtered to the source area's site.
                items:
                  type: string
                  format: object-id
    CreateBookableAreaAvailabilityRule:
      description: |
        Body for creating a new `AvailabilityRule` on a `BookableArea`.
        Only `is_available` is required; the remaining fields filter when
        the rule applies.
      required: true
      content:
        application/json:
          schema:
            title: CreateBookableAreaAvailabilityRule
            allOf:
              - $ref: '#/components/schemas/UpdateBookableAreaAvailabilityRule-content-application~1json-schema'
    UpdateBookableAreaAvailabilityRule:
      description: |
        Body for updating an existing `AvailabilityRule`. `is_available`
        is required (the same validator runs on create + update
        server-side); every other field is optional and overrides the
        current value when sent.
      required: true
      content:
        application/json:
          schema:
            title: UpdateBookableAreaAvailabilityRule
            type: object
            additionalProperties: false
            required:
              - is_available
            properties:
              is_available:
                type: boolean
                description: Whether the window is bookable. `false` rules override `true` rules.
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Daily start time in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: Daily end time in `HH:MM`.
                example: '18:00'
              weekdays:
                type: array
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
    UpdateCourseType:
      description: |
        Body for updating an existing `CourseType`. Every field is
        optional; only fields you send are written. Fields you omit retain
        their current values.

        Requires the `SETTINGS_MANAGE` permission on the course type's
        site.
      required: true
      content:
        application/json:
          schema:
            title: UpdateCourseType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the course type.
                example: 5-Pack Aromatherapy Massage
              currency:
                $ref: '#/components/schemas/properties_currency'
              description:
                type: string
                nullable: true
                description: |
                  Markdown-rendered long-form description shown to
                  customers when they're selecting the course type.
                example: |
                  Five 60-minute aromatherapy massages, valid for 12 months
                  from purchase.
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this course type, in the smallest
                  currency unit (e.g. pence). Pass `null` to clear a
                  previously-set standard price.
                example: 5000
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map this course type to an
                  external POS or PMS catalog.
                example: COURSE-AROMA-5
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this offering. Free-form.
                example: ext-aroma-5
              offered_online:
                type: boolean
                description: When `true`, this course type can be purchased via the public shopfront.
              private:
                type: boolean
                description: When `true`, the course type is hidden from the public shopfront listing but remains purchasable via direct link.
              visibility:
                $ref: '#/components/schemas/visibility'
              offering_type:
                type: string
                description: |
                  Deprecated. Legacy single-offering type pointer; new
                  callers populate `offerings` instead. See `CreateCourseType`.
                enum:
                  - area_booking
                  - appointment
                  - product
                  - session
              offering_id:
                type: string
                format: object-id
                nullable: true
                description: |
                  Deprecated. Legacy single-offering ID; new callers
                  populate `offerings` instead.
              offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              upsell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              meta:
                title: UpdateCourseTypeMeta
                type: object
                additionalProperties: false
                description: SEO meta-overrides for the course type's shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                    description: HTML `<title>` override (max 120 chars).
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
                    description: HTML meta description override (max 140 chars).
              quantity:
                type: integer
                minimum: 1
                description: Number of credits the course grants when purchased.
                example: 5
              credits_validity_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration string for how long credits remain
                  redeemable. `null` = credits never expire.
                example: P1Y
              image_id:
                type: string
                format: object-id
                nullable: true
                description: ID of an uploaded `Media` to use as the course type's hero image.
              customers_only:
                type: boolean
                description: When `true`, only signed-in customers can purchase.
              members_only:
                type: boolean
                description: |
                  When `true`, only customers with an active membership of
                  one of the `permitted_membership_type_ids` can purchase.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  When `members_only: true`, the list of `MembershipType`
                  IDs whose holders are eligible to purchase.
                items:
                  type: string
                  format: uuid
              category_ids:
                type: array
                description: Category IDs the course type belongs to.
                items:
                  type: string
                  format: object-id
              revenue_centre:
                type: string
                nullable: true
                description: Free-form revenue centre code for accounting reports.
                example: SPA-CREDITS
    UpdateCourseTypeLocaleStrings:
      description: Update locale strings for a CourseType
      required: true
      content:
        application/json:
          schema:
            title: UpdateCourseTypeLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this course type in the given locale.
                example: Beginner Yoga Course
              description:
                type: string
                nullable: true
                description: The localised description for this course type in the given locale.
                example: A 6-week introductory yoga course for beginners.
              meta_title:
                type: string
                nullable: true
                description: The localised meta title for this course type in the given locale.
                example: Beginner Yoga Course | Book Now
              meta_description:
                type: string
                nullable: true
                description: The localised meta description for this course type in the given locale.
                example: Join our beginner yoga course and develop flexibility, strength and mindfulness.
    CreateCourseTypeAvailabilityRule:
      description: |
        Body for creating a new `AvailabilityRule` on a `CourseType`. Only
        `is_available` is required. `date_to`, if set, must be on or after
        `date_from`.
      required: true
      content:
        application/json:
          schema:
            title: CreateCourseTypeAvailabilityRule
            allOf:
              - $ref: '#/components/schemas/UpdateCourseTypeAvailabilityRule-content-application~1json-schema'
    UpdateCourseTypeAvailabilityRule:
      description: |
        Body for updating an existing `AvailabilityRule` on a `CourseType`.
        `is_available` is required (the same validator runs on create +
        update server-side); date fields are optional and override current
        values when sent.
      required: true
      content:
        application/json:
          schema:
            title: UpdateCourseTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: Whether the rule opens or closes the window.
                example: true
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies. Must be ≥ date_from.
                example: '2026-08-31'
            required:
              - is_available
    CopyCourseType:
      description: |
        Body for copying a `CourseType`. `name` is required so the new
        copy is distinguishable from the source; all other fields are
        optional overrides. Fields omitted are inherited from the source.
      required: true
      content:
        application/json:
          schema:
            title: CopyCourseType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new copy. Plain text only — HTML
                  tags are rejected. Required so the copy is distinguishable
                  from the source.
                example: Pilates 10-class Course (Evenings)
              description:
                type: string
                nullable: true
                description: |
                  Long-form description shown to customers. Markdown
                  rendered.
                example: |
                  A 10-class pilates course running on weekday evenings.
                  Credits valid for 12 months from purchase.
              product_code:
                type: string
                nullable: true
                description: External POS/PMS product code.
                example: PIL-10-EVE
              external_id:
                type: string
                nullable: true
                description: External identifier for integrations.
                example: ext-course-pil10
              currency:
                $ref: '#/components/schemas/properties_currency'
              standard_price:
                type: integer
                nullable: true
                description: |
                  Override the standard price on the copy, in the smallest
                  currency unit (e.g. pence). Defaults to the source's
                  standard price when omitted.
                example: 5000
              offered_online:
                type: boolean
                description: Whether bookable via the public shopfront.
              private:
                type: boolean
                description: When true, only customers with the direct link can purchase.
              visibility:
                type: string
                description: |
                  Visibility override. `public` = everyone; `hidden` = out
                  of search/browse (still purchasable by direct link);
                  `members_only` = restricted to permitted membership-type
                  holders.
                enum:
                  - public
                  - hidden
                  - members_only
              offering_type:
                type: string
                description: |
                  The type of offering the course wraps. Determines which
                  `Offering` ID the `offering_id` field references. **Note:**
                  this field will be removed once the `multiple_course_offerings`
                  feature flag is fully rolled out.
                enum:
                  - area-booking
                  - appointment
                  - product
                  - session
              offering_id:
                type: string
                nullable: true
                description: |
                  Identifier of the single underlying offering this course
                  bundles (matched against the type set in `offering_type`).
                  **Note:** this field will be removed once the
                  `multiple_course_offerings` feature flag rolls out — use
                  `offerings` instead, which supports multiple offerings
                  per course.
                example: 5f1234567890abcdef123456
              offerings:
                type: array
                description: |
                  Multiple offerings bundled by this course. Each entry pairs
                  an offering ID with its type.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              upsell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              quantity:
                type: integer
                minimum: 1
                description: |
                  Number of redemptions the course grants the purchaser
                  (e.g. a 10-class card has `quantity: 10`).
                example: 10
              credits_validity_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration during which the course credits remain
                  redeemable after purchase. Null = no expiry.
                example: P12M
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` for the cover image.
                example: 5f1234567890abcdef123456
              customers_only:
                type: boolean
                description: Restrict purchase to registered customers.
              members_only:
                type: boolean
                description: Restrict purchase to permitted membership-type holders.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: Membership-type IDs allowed to purchase when `members_only=true`.
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Category IDs for shopfront grouping.
              revenue_centre:
                type: string
                nullable: true
                description: Revenue centre to post course sales to. Must be valid for the source course type's site.
                example: course-sales
              meta:
                type: object
                title: CopyCourseTypeMeta
                additionalProperties: false
                description: SEO metadata for the public shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
            required:
              - name
    CreateCourseTypePriceRule:
      description: |
        Body for creating a new `PriceRule` on a `CourseType`. Only `price`
        is required. `date_to` must be on or after `date_from` if both are
        set.
      required: true
      content:
        application/json:
          schema:
            title: CreateCourseTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: Price in the smallest currency unit (e.g. pence, cents). `12000` is £120.00 on a GBP site.
                example: 12000
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive). Defaults to today in the course type's timezone when omitted.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date this rule applies (inclusive). Must be on or
                  after `date_from` if both are set. Null = no end date.
                example: '2026-08-31'
            required:
              - price
    UpdateCourseTypePriceRule:
      description: Body for updating an existing `PriceRule` on a `CourseType`. All fields optional.
      required: true
      content:
        application/json:
          schema:
            title: UpdateCourseTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: Price in the smallest currency unit.
                example: 12000
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies. Must be ≥ date_from.
                example: '2026-08-31'
    CreateEquipment:
      description: |
        Body for creating a new `Equipment` record. `name`, `quantity`, and
        `site_id` are required. `organisation_id` defaults to the caller's
        primary organisation when omitted.
      required: true
      content:
        application/json:
          schema:
            title: CreateEquipment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name. Plain text only.
                example: Steam Machine A
              description:
                type: string
                nullable: true
                description: Optional internal note (model, service schedule, location).
                example: Lucas Champion steam unit serviced annually.
              quantity:
                type: number
                description: |
                  Number of units of this equipment the site has. Used by
                  the availability engine to enforce concurrency limits.
                  Must be greater than 0.
                example: 2
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the site to create this equipment under. The
                  caller's API key must have access to the site.
                example: 11111111-1111-1111-1111-111111111111
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation to attribute this equipment to.
                  Defaults to the caller's primary organisation if omitted.
                example: 22222222-2222-2222-2222-222222222222
            required:
              - name
              - quantity
              - site_id
    UpdateEquipment:
      description: |
        Body for updating an existing `Equipment` record. Every field is
        optional; omitted fields keep their current values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateEquipment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name shown to staff in the admin UI. Plain text
                  only — HTML tags are rejected.
                example: Steam Machine A (refurbished)
              description:
                type: string
                nullable: true
                description: |
                  Optional internal note about this equipment — model
                  number, service schedule, location. Not surfaced to
                  customers.
                example: Lucas Champion steam unit serviced 2026-04-15.
              quantity:
                type: number
                description: Number of units. Must be greater than 0.
                example: 3
              site_id:
                type: string
                format: uuid
                description: |
                  Move the equipment to a different site. The caller's API
                  key must have access to both the old and new site.
                example: 11111111-1111-1111-1111-111111111111
    CreateDiscountType:
      description: Create a `DiscountType`
      content:
        application/json:
          schema:
            title: CreateDiscountType
            type: object
            additionalProperties: false
            properties:
              applicable_for:
                type: string
                description: Where the discount type is able to be applied.
                example: app_and_booking_engine
                enum:
                  - app_only
                  - app_and_booking_engine
              code:
                type: string
                description: |
                  The code for the discount type.
                  When the type is a promo code, this will be what the customer enters in on the booking engine to receive their discount, e.g. `SUMMER23`.
                  Or, if the discount type is for app use, this is what is used for reporting.
                example: SUMMER23
              description:
                type: string
                description: |
                  This provides further details on what the discount type can be used for.
                  It's up to the user to provide this.
                example: For 15% off any order placed from Jun-Aug 2023
                nullable: true
              amount_type:
                type: string
                description: |
                  The type of discount. For a promo code, this will always be a percentage.
                example: percentage
                enum:
                  - monetary
                  - percentage
              discount_amount:
                type: integer
                description: |
                  The value of the discount to be applied when a discount type is used.
                  This can be used as a monetary amount or percentage for an in-app discount type and is set to percentage for a promo code.
                example: 15
                nullable: true
              is_custom_amount:
                type: boolean
                default: false
                example: false
                description: |
                  Whether the amount provided is customisable.
                  This can only be toggled for in-app discount types.
              valid_from:
                type: string
                format: date
                description: |
                  The start date which the promo code is valid from, based on the date the order is submitted.
                  This field is null if `applicable_for` is set to `app_only`.
                  For a promo code to be valid for use on an order, this must be set.
                example: '2023-06-01'
                nullable: true
              valid_to:
                type: string
                format: date
                description: |
                  The end date which the promo code is valid until, based on the date the order is submitted.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-09-01'
                nullable: true
              item_date_from:
                type: string
                format: date
                description: |
                  The start date for when the purchased item occurs, based on the date the item is booked for.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-09-01'
                nullable: true
              item_date_to:
                type: string
                format: date
                description: |
                  The end date for when the purchased item occurs, based on the date the item is booked for.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-09-30'
                nullable: true
              item_date_weekdays:
                type: array
                description: |
                  The days the purchased item takes place on.
                  For example, the promo code could be valid for massages which only occur on Mondays.
                  By default, this array contains all enum values and the occurrence of the purchased items is not restricted to any days.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
              item_time_from:
                type: string
                description: |
                  The start time for when the purchased item takes place.
                  For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '10:00'
                nullable: true
              item_time_to:
                type: string
                description: |
                  The end time for when the purchased item takes place.
                  For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '14:00'
                nullable: true
              valid_offerings:
                type: array
                description: |
                  An array of offerings which the promo code is valid for.
                  By default, this array is empty and the discount will not be applied to any items in the order.
                  If this array includes offerings, the discount will be applied to only those selected items in the order.
                items:
                  $ref: '#/components/schemas/OfferingIdentifierRequest'
              max_uses:
                type: integer
                description: |
                  The maximum number of times the code can be used in total.
                  By default, this value is null which means that this number is unlimited.
                example: 100000
                nullable: true
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this discount type belongs to.
                  Discount types are scoped per site so each location can
                  maintain its own promo codes, staff discounts, and loyalty
                  offers. The caller's API key must have access to this site.
            required:
              - applicable_for
              - code
              - site_id
    UpdateDiscountTypeOrder:
      description: Update the order of Discount Types
      content:
        application/json:
          schema:
            title: UpdateDiscountTypeOrder
            type: object
            additionalProperties: false
            properties:
              discount_type_ids:
                type: array
                items:
                  type: string
                  format: uuid
                  description: The ID of the discount type.
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site whose discount types are being
                  reordered. All IDs in `discount_type_ids` must belong to
                  this site; the caller's API key must have access to it.
            required:
              - discount_type_ids
              - site_id
    UpdateDiscountType:
      description: Update a `DiscountType`
      content:
        application/json:
          schema:
            type: object
            title: UpdateDiscountType
            additionalProperties: false
            properties:
              applicable_for:
                type: string
                description: Where the discount type is able to be applied.
                example: app_and_booking_engine
                enum:
                  - app_only
                  - app_and_booking_engine
              code:
                type: string
                description: |
                  The code for the discount type.
                  When the type is a promo code, this will be what the customer enters in on the booking engine to receive their discount, e.g. `SUMMER23`.
                  Or, if the discount type is for app use, this is what is used for reporting.
                  If `has_been_redeemed` is true, this field is removed from the request.
                example: SUMMER23
              description:
                type: string
                description: |
                  This provides further details on what the discount type can be used for.
                  It's up to the user to provide this.
                example: For 15% off any order placed from Jun-Aug 2023
                nullable: true
              amount_type:
                type: string
                description: |
                  The type of discount. For a promo code, this will always be a percentage.
                example: percentage
                enum:
                  - monetary
                  - percentage
              discount_amount:
                type: integer
                description: |
                  The value of the discount to be applied when a discount type is used.
                  This can be used as a monetary amount or percentage for an in-app discount type and is set to percentage for a promo code.
                example: 15
                nullable: true
              is_custom_amount:
                type: boolean
                default: false
                example: false
                description: |
                  Whether the amount provided is customisable.
                  This can only be toggled for in-app discount types.
              valid_from:
                type: string
                format: date
                description: |
                  The start date which the promo code is valid from, based on the date the order is submitted.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-06-01'
                nullable: true
              valid_to:
                type: string
                format: date
                description: |
                  The end date which the promo code is valid until, based on the date the order is submitted.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-09-01'
                nullable: true
              item_date_from:
                type: string
                format: date
                description: |
                  The start date for when the purchased item occurs, based on the date the item is booked for.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-09-01'
                nullable: true
              item_date_to:
                type: string
                format: date
                description: |
                  The end date for when the purchased item occurs, based on the date the item is booked for.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '2023-09-30'
                nullable: true
              item_date_weekdays:
                type: array
                description: |
                  The days the purchased item takes place on.
                  For example, the promo code could be valid for massages which only occur on Mondays.
                  By default, this array contains all enum values and the occurrence of the purchased items is not restricted to any days.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
              item_time_from:
                type: string
                description: |
                  The start time for when the purchased item takes place.
                  For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '10:00'
                nullable: true
              item_time_to:
                type: string
                description: |
                  The end time for when the purchased item takes place.
                  For example, the promo code could be valid for off-peak massages taking place from 4-6pm.
                  This field is null if `applicable_for` is set to `app_only`.
                  This field is also null if it hasn't been set when `applicable_for` is set to `app_and_booking_engine`.
                example: '14:00'
                nullable: true
              valid_offerings:
                type: array
                description: |
                  An array of offerings which the promo code is valid for.
                  By default, this array is empty and the discount will not be applied to any items in the order.
                  If this array includes offerings, the discount will be applied to only those selected items in the order.
                items:
                  $ref: '#/components/schemas/OfferingIdentifierRequest'
              max_uses:
                type: integer
                description: |
                  The maximum number of times the code can be used in total.
                  By default, this value is null which means that this number is unlimited.
                example: 100000
                nullable: true
              has_been_redeemed:
                type: boolean
                default: false
                example: false
                description: |
                  Whether the promo code has been used by at least one customer.
                  If this value is true, the `code` field is removed from the request.
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this discount type belongs to.
                  Discount types are scoped per site so each location can
                  maintain its own promo codes, staff discounts, and loyalty
                  offers. The caller's API key must have access to this site.
    CopyDiscountType:
      description: Copy an existing `DiscountType`
      content:
        application/json:
          schema:
            type: object
            title: CopyDiscountType
            additionalProperties: false
            properties:
              code:
                type: string
                description: |
                  The code for the discount type.
                  When the type is a promo code, this will be what the customer enters in on the booking engine to receive their discount, e.g. `SUMMER23`.
                  Or, if the discount type is for app use, this is what is used for reporting.
                  If `has_been_redeemed` is true, this field is removed from the request.
                example: SUMMER23
              description:
                type: string
                description: |
                  This provides further details on what the discount type can be used for.
                  It's up to the user to provide this.
                example: For 15% off any order placed from Jun-Aug 2023
                nullable: true
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site the copied discount type should
                  belong to. Lets you duplicate a discount type from one
                  site into another within the same organisation.
    CreateExternalIdType:
      description: Create an `ExternalIdType`
      content:
        application/json:
          schema:
            title: CreateExternalIdTypeRequest
            type: object
            additionalProperties: false
            required:
              - key
              - name
              - applies_to
            properties:
              key:
                type: string
                pattern: ^[a-z_]+$
                description: |
                  Machine-readable identifier used when reading and writing
                  external IDs on objects. Lowercase letters and
                  underscores only, must be unique within the organisation,
                  and cannot be changed after creation.
                example: my_external_system
              name:
                type: string
                description: |
                  Display name of the external ID type, shown to staff in
                  the admin UI alongside the IDs themselves. Use a clear
                  system-of-record label (e.g. "Salesforce CRM").
                  1-120 characters.
                example: My External System
              description:
                type: string
                description: |
                  Optional help text shown next to the external ID type in
                  the admin UI to explain to staff what the ID represents
                  and where it comes from. Plain text, up to 500 characters.
                example: ID of the basket in my external system
              applies_to:
                type: string
                description: The type of object the external ID type applies to.
                enum:
                  - basket
              site_ids:
                type: array
                items:
                  type: string
                  format: uuid
                  description: The ID of the site the external ID type should be associated with.
              all_sites:
                type: boolean
                description: Whether the external ID type should be associated with all sites.
    UpdateExternalIdType:
      description: Update an `ExternalIdType`
      content:
        application/json:
          schema:
            type: object
            title: UpdateExternalIdType
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the external ID type, shown to staff in
                  the admin UI alongside the IDs themselves. Use a clear
                  system-of-record label (e.g. "Salesforce CRM").
                  1-120 characters.
                example: My External System
              description:
                type: string
                nullable: true
                description: |
                  Optional help text shown next to the external ID type in
                  the admin UI to explain to staff what the ID represents
                  and where it comes from. Plain text, up to 500 characters.
                example: ID of the basket in my external system
              applies_to:
                type: string
                description: The type of object the external ID type applies to.
                enum:
                  - basket
              site_ids:
                type: array
                items:
                  type: string
                  format: uuid
                  description: The ID of the site the external ID type should be associated with.
              all_sites:
                type: boolean
                description: Whether the external ID type should be associated with all sites.
    AddExternalIdTypeSite:
      description: Add a site to an `ExternalIdType`
      content:
        application/json:
          schema:
            title: AddExternalIdTypeSite
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site to associate with this external ID
                  type. Once associated, baskets and other supported objects
                  at this site can carry an external ID of this type.
            required:
              - site_id
    CreateIntakeFormQuestion:
      description: |
        Body for creating a new `IntakeFormQuestion` in the parent section.
        The `question` and `type` fields are required; every other field is
        optional, but `multiple_choice_answers` is required (≥ 2 entries)
        when `type=multiple_choice`.
      required: true
      content:
        application/json:
          schema:
            title: CreateIntakeFormQuestion
            type: object
            additionalProperties: false
            allOf:
              - $ref: '#/components/schemas/IntakeFormQuestionWritableFields'
              - type: object
                additionalProperties: false
                required:
                  - question
                  - type
    OrderIntakeFormQuestions:
      required: true
      content:
        application/json:
          schema:
            title: OrderIntakeFormQuestions
            type: object
            additionalProperties: false
            properties:
              intake_form_question_ids:
                type: array
                description: An ordered list of intake form question IDs. Must contain at least 2 items.
                minItems: 2
                items:
                  type: string
              site_id:
                type: string
                description: ID of the site whose intake-form question order should be updated. The caller's API key must have access to this site and to the parent intake form section.
                example: 9c7e0e8c-8d4d-4a6e-9f0c-3a4b5c6d7e8f
            required:
              - intake_form_question_ids
              - site_id
    CreatePackage:
      description: |
        Body for creating a new `Package`. `name` and `site_id` are required;
        everything else has a sensible default or `null`-equivalent. See
        `Package` in `schemas.yml` for the full field list and their semantics
        — this body accepts the same write-able fields plus `site_id` (which
        determines which site the package is offered at).

        **`item_choices` are intentionally omitted from this body shape**:
        the full nested structure (`allocation`, `start_time_rules`, nested
        `options`, etc.) is documented on the `Package` schema and on the
        sibling item-choice endpoints. The store endpoint accepts an
        `item_choices` array; its shape mirrors `PackageItemChoice` from the
        `Package` schema.
      required: true
      content:
        application/json:
          schema:
            title: CreatePackage
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the package. Visible to customers in the
                  shopfront and to staff in the admin UI. Plain text only.
                example: Couples Spa Day
              description:
                type: string
                description: |
                  Long-form description shown to customers when they're
                  browsing the package. Markdown is rendered.
                example: |
                  A full day of relaxation for two — includes a 60-minute
                  massage each, a two-course lunch, and full access to the
                  thermal suite.
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map this package to an
                  external POS or PMS catalog. Free-form string; uniqueness
                  is not enforced server-side.
                example: PKG-COUPLES-DAY
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this offering. Free-form.
                example: ext-couples-spa-day
              currency:
                $ref: '#/components/schemas/properties_currency'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this package, in the smallest
                  currency unit (e.g. pence). Optional at create time —
                  packages can be created without a standard price and
                  have one configured later.
                example: 5000
              site_id:
                type: string
                description: |
                  ID of the site to offer this package at. The caller's API
                  key must have access to the site; requests for a site they
                  don't own get 422.
                example: 00000000-0000-0000-0000-111111111111
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation to attribute this offering to.
                  Defaults to the caller's primary organisation if omitted.
                example: 00000000-0000-0000-0000-aaaaaaaaaaaa
              availability_rules:
                type: array
                description: |
                  Per-day availability rules controlling when this package
                  can be booked. See `AvailabilityRule` for shape.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              offered_online:
                type: boolean
                description: |
                  When true, the package is bookable via the public
                  shopfront. When false, it's bookable only via the admin UI.
                  Defaults to false.
              private:
                type: boolean
                description: |
                  When true, only customers with the direct link can book
                  this package — it's hidden from category pages and search
                  engines.
              visibility:
                type: string
                description: |
                  Visibility override controlling who can see this package
                  on the shopfront. `public` shows it everywhere; `link_only`
                  keeps it out of browse/search (still bookable by direct
                  link); `private` restricts it to admin booking flows.
                enum:
                  - public
                  - link_only
                  - private
                example: public
              customers_only:
                type: boolean
                description: When true, only registered customers (not guests) can book this package.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book this package.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership type IDs whose members are allowed to book this
                  package. Only relevant when `members_only=true`. Membership
                  types from outside the site's brand are silently filtered
                  out.
                items:
                  type: string
                  format: uuid
                example:
                  - 00000000-0000-0000-0000-membership001
              membership_booking_windows_enabled:
                type: boolean
                description: |
                  When true, members can book this package further in
                  advance than the standard window. The exact extra advance
                  per membership type is defined in `membership_booking_windows`.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-booking-window overrides.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              item_choices:
                type: array
                description: |
                  The choices customers make when booking this package
                  (e.g. "pick a massage", "pick a lunch course"). Each
                  choice has an allocation, options, start-time rules, and
                  visibility flags. The detailed shape is documented as
                  `PackageItemChoice` under the `Package` schema —
                  the create endpoint accepts the same object shape.
                items:
                  type: object
                  additionalProperties: true
              upsell_offerings:
                type: array
                description: Other offerings to upsell on the booking confirmation page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Other offerings to cross-sell during the booking flow.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Retail products to display as related to this package on its shopfront page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              category_ids:
                type: array
                description: Category IDs the package belongs to. Used for shopfront grouping.
                items:
                  type: string
                example:
                  - 5e932c0901d210625e3a8766
              meta:
                type: object
                title: CreatePackageMeta
                additionalProperties: false
                description: SEO metadata for the public shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                    description: SEO `<title>`. Falls back to the package name when omitted.
                    example: Couples Spa Day at Riverside Retreat
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
                    description: SEO meta description. Falls back to the package description when omitted.
                    example: A relaxing day for two with massages, lunch, and thermal suite access.
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: |
                  Whether and when customers can cancel a booking of this
                  package themselves. `allowed` = always; `if_unpaid` = only
                  if no payment has been taken; `disallowed` = never (admin
                  only).
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the package's start during which
                  cancellation is no longer permitted. e.g. `PT24H` = no
                  cancellation in the last 24 hours.
                example: PT24H
              customer_reschedule_permitted:
                description: Whether customers can reschedule a package of this type themselves.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the package's start during which
                  rescheduling is no longer permitted. e.g. `PT24H` = no
                  rescheduling in the last 24 hours.
                example: PT24H
              max_daily_duration:
                type: integer
                nullable: true
                minimum: 0
                description: |
                  Maximum minutes between the start of the first and end of
                  the last item on each day of the package. Use this to
                  cap how spread-out a single-day package can become.
                example: 240
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers
                  can book this package. e.g. `P2W` = up to two weeks ahead.
                example: P2W
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how soon before the package
                  start a customer can book. e.g. `P2D` = at least two days'
                  notice.
                example: P2D
              min_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Minimum number of guests for a single booking of this package.
                example: 2
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum number of guests for a single booking. Must be
                  `>= min_guests`. Server-side, `separate_couples_package_choices`
                  is forced to `false` unless both `min_guests` and
                  `max_guests` equal `2`.
                example: 2
              prevent_choice_overlaps:
                type: boolean
                nullable: true
                description: Whether to prevent booking choices in this package from overlapping times.
              separate_couples_package_choices:
                type: boolean
                nullable: true
                description: |
                  For couples packages (both `min_guests` and `max_guests`
                  equal `2`), whether each guest can independently pick
                  choices. Forced to `false` for any other guest configuration.
              email_options:
                type: object
                title: CreatePackageEmailOptions
                additionalProperties: false
                description: Email-rendering options for this package.
                properties:
                  hide_prices:
                    type: boolean
                    description: |
                      When true, prices are hidden from customer emails
                      for cases where the customer didn't pay directly
                      (e.g. corporate or comped bookings).
              overnight_package_config:
                type: object
                title: CreatePackageOvernightConfig
                additionalProperties: false
                description: |
                  Configuration for overnight packages — packages that include
                  a hotel room reservation alongside their other items.
                  When `enabled=true`, both `rate_id` and `num_nights` are
                  required.
                properties:
                  enabled:
                    type: boolean
                    description: Whether this package is an overnight package.
                    example: true
                  rate_id:
                    type: string
                    nullable: true
                    description: |
                      ID of the PMS rate code the overnight package books
                      against. Required when `enabled=true`.
                    example: rate-king-bb
                  num_nights:
                    type: integer
                    nullable: true
                    minimum: 1
                    description: Number of nights the package books. Required when `enabled=true`.
                    example: 1
              include_pricing_on_calendar:
                type: boolean
                description: Whether to surface the price alongside this package in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum bookings of this package per basket.
                example: 1
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum bookings of this package per individual guest within a basket.
                example: 1
            required:
              - name
              - site_id
    UpdatePackage:
      description: |
        Partial update for an existing `Package`. Every field is optional;
        send only the ones you want to change. Most fields mirror
        `CreatePackage`; note that `site_id` and `organisation_id` are fixed
        at create time and cannot be changed here.

        **`item_choices` shape**: the full nested structure is documented
        on the `Package` schema (`PackageItemChoice`). The update endpoint
        accepts an array of objects in the same shape.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePackage
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name. Plain text only.
                example: Couples Spa Day
              description:
                type: string
                description: Long-form description shown to customers. Markdown is rendered.
                example: |
                  A full day of relaxation for two — includes a 60-minute
                  massage each, a two-course lunch, and full access to the
                  thermal suite.
              product_code:
                type: string
                nullable: true
                description: External POS/PMS product code.
                example: PKG-COUPLES-DAY
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations.
                example: ext-couples-spa-day
              currency:
                $ref: '#/components/schemas/properties_currency'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this package, in the smallest
                  currency unit (e.g. pence). Pass `null` to clear a
                  previously-set standard price.
                example: 5000
              availability_rules:
                type: array
                description: Per-day availability rules.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              offered_online:
                type: boolean
                description: Whether the package is bookable via the public shopfront.
              private:
                type: boolean
                description: When true, only customers with the direct link can book this package.
              visibility:
                type: string
                description: |
                  Visibility override controlling who can see this package
                  on the shopfront. Same semantics as on create.
                enum:
                  - public
                  - link_only
                  - private
              customers_only:
                type: boolean
                description: Restrict booking to registered customers.
              members_only:
                type: boolean
                description: Restrict booking to permitted membership-type holders.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: Membership types whose members can book when `members_only=true`.
                example:
                  - 00000000-0000-0000-0000-membership001
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to apply per-membership-type advance-booking windows.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-window overrides.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              item_choices:
                type: array
                description: |
                  Replacement set of item choices for this package. Same
                  shape as `PackageItemChoice` on the `Package` schema.
                items:
                  type: object
                  additionalProperties: true
              upsell_offerings:
                type: array
                description: Upsell candidates at booking confirmation.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Cross-sell candidates during booking.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Retail products to surface as related on the package's shopfront page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              category_ids:
                type: array
                description: Category IDs for shopfront grouping.
                items:
                  type: string
                example:
                  - 5e932c0901d210625e3a8766
              meta:
                type: object
                title: UpdatePackageMeta
                additionalProperties: false
                description: SEO metadata for the shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: Customer self-cancellation policy.
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which cancellation is locked.
                example: PT24H
              customer_reschedule_permitted:
                description: Updated self-reschedule policy for this package.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which rescheduling is locked.
                example: PT24H
              max_daily_duration:
                type: integer
                nullable: true
                minimum: 0
                description: Maximum minutes between first-item start and last-item end on each day.
                example: 240
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 maximum advance-booking duration.
                example: P2W
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 minimum advance-booking duration.
                example: P2D
              min_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Minimum guests per booking.
                example: 2
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  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.
                example: 2
              prevent_choice_overlaps:
                type: boolean
                nullable: true
                description: Whether to prevent booking choices in this package from overlapping times.
              separate_couples_package_choices:
                type: boolean
                nullable: true
                description: |
                  For couples packages, whether each guest can independently
                  pick choices. Forced to `false` for any other guest
                  configuration.
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` to use as the cover image. Pass `null` to clear.
                example: 5f1234567890abcdef123456
              default_revenue_centre:
                type: string
                nullable: true
                description: |
                  Default revenue centre identifier to fall back to when
                  balancing allocations. Must be a valid revenue centre at
                  the package's site.
                example: spa-treatments
              email_options:
                type: object
                title: UpdatePackageEmailOptions
                additionalProperties: false
                description: Email-rendering options for this package.
                properties:
                  hide_prices:
                    type: boolean
                    description: Hide prices on customer emails where the customer didn't pay directly.
              overnight_package_config:
                type: object
                title: UpdatePackageOvernightConfig
                additionalProperties: false
                description: |
                  Overnight-package configuration. When `enabled=true`, both
                  `rate_id` and `num_nights` must be set (either in this
                  request or already on the package).
                properties:
                  enabled:
                    type: boolean
                    description: Whether this package is an overnight package.
                  rate_id:
                    type: string
                    nullable: true
                    description: PMS rate code ID. Required when `enabled=true`.
                    example: rate-king-bb
                  num_nights:
                    type: integer
                    nullable: true
                    minimum: 1
                    description: Number of nights. Required when `enabled=true`.
                    example: 1
              include_pricing_on_calendar:
                type: boolean
                description: Surface prices in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Max of this package per basket.
                example: 1
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Max of this package per guest per basket.
                example: 1
    CopyPackage:
      description: |
        Body for copying a `Package`. Every field is optional — anything you
        omit is inherited from the source unchanged, so the simplest call is
        an empty body. Pass `name` to make the copy distinguishable from the
        source in admin lists.

        Note: `price` is accepted here as a flat overrideable amount (in the
        smallest currency unit), even though packages normally use price
        rules. This mirrors the legacy copy behaviour.
      required: true
      content:
        application/json:
          schema:
            title: CopyPackage
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the new copy. Strongly recommended so the copy is distinguishable from the source.
                example: Couples Spa Day (Premium)
              description:
                type: string
                description: |
                  Override the customer-facing long-form description on the
                  copy. Defaults to the source's description when omitted.
                  Markdown rendered.
                example: |
                  An elevated couples day with extended treatments and
                  private terrace access.
              external_id:
                type: string
                nullable: true
                description: |
                  Override external identifier on the copy. Defaults to
                  `null` so integrations don't accidentally see two
                  offerings with the same external id.
                example: ext-couples-spa-day-premium
              price:
                type: integer
                description: |
                  Flat base price (in the smallest currency unit, e.g.
                  pence/cents) to set on the copy. Most packages prefer
                  `price_rules`; this field is a convenience for the simple
                  case.
                example: 25000
              standard_price:
                type: integer
                nullable: true
                description: |
                  Override the standard price on the copy, in the smallest
                  currency unit (e.g. pence). Defaults to the source's
                  standard price when omitted.
                example: 25000
              currency:
                $ref: '#/components/schemas/properties_currency'
              availability_rules:
                type: array
                description: Override the per-day availability rules on the copy.
                items:
                  $ref: '#/components/schemas/AvailabilityRule'
              offered_online:
                type: boolean
                description: Whether the copy is bookable via the public shopfront. Defaults to the source's value.
              private:
                type: boolean
                description: When true, only customers with the direct link can book the copy.
              visibility:
                type: string
                description: Visibility override on the copy. Same semantics as on the source.
                enum:
                  - public
                  - link_only
                  - private
              customers_only:
                type: boolean
                description: When true, only registered customers (not guests) can book the copy.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book the copy.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership types whose members can book the copy when
                  `members_only=true`.
                items:
                  type: string
                  format: uuid
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to apply per-membership-type advance-booking windows on the copy.
              membership_booking_windows:
                type: array
                description: Per-membership-type advance-window overrides on the copy.
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              upsell_offerings:
                type: array
                description: Override the upsell candidates surfaced at booking confirmation on the copy.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Override the cross-sell candidates surfaced during the booking flow on the copy.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Override the related retail products on the copy's shopfront page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              meta:
                type: object
                title: CopyPackageMeta
                additionalProperties: false
                description: SEO metadata for the copy's shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
              customer_cancellation_permitted:
                type: string
                nullable: true
                description: |
                  Customer self-cancellation policy on the copy. `allowed` =
                  always; `if_unpaid` = only if no payment has been taken;
                  `disallowed` = never.
                enum:
                  - allowed
                  - if_unpaid
                  - disallowed
              customer_cancellation_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the package start during which
                  cancellation is no longer permitted on the copy.
                example: PT24H
              customer_reschedule_permitted:
                description: Self-reschedule policy applied to the copied package.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration before the package start during which
                  rescheduling is no longer permitted on the copy.
                example: PT24H
              max_daily_duration:
                type: integer
                minimum: 0
                description: Maximum minutes between first-item start and last-item end on each day for the copy.
                example: 240
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers
                  can book the copy.
                example: P2W
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how soon before the package
                  start a customer can book the copy.
                example: P2D
              min_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Minimum guests per booking of the copy.
                example: 2
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum guests per booking of the copy.
                example: 2
              prevent_choice_overlaps:
                type: boolean
                description: Whether to prevent booking choices in the copy from overlapping times.
              separate_couples_package_choices:
                type: boolean
                nullable: true
                description: |
                  For couples packages, whether each guest can independently
                  pick choices on the copy. Forced to `false` for any other
                  guest configuration.
              email_options:
                type: object
                title: CopyPackageEmailOptions
                additionalProperties: false
                description: Email-rendering options for the copy.
                properties:
                  hide_prices:
                    type: boolean
                    description: Hide prices on customer emails for the copy.
              overnight_package_config:
                type: object
                title: CopyPackageOvernightConfig
                additionalProperties: false
                description: |
                  Overnight-package configuration on the copy. When
                  `enabled=true`, both `rate_id` and `num_nights` are
                  required.
                properties:
                  enabled:
                    type: boolean
                    description: Whether the copy is an overnight package.
                  rate_id:
                    type: string
                    nullable: true
                    description: PMS rate code ID. Required when `enabled=true`.
                    example: rate-king-bb
                  num_nights:
                    type: integer
                    nullable: true
                    minimum: 1
                    description: Number of nights. Required when `enabled=true`.
                    example: 1
              include_pricing_on_calendar:
                type: boolean
                description: Whether to surface the price alongside the copy in calendar views.
              max_per_basket:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of the copy per basket.
                example: 1
              max_per_guest:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum number of the copy per individual guest per basket.
                example: 1
    UpdatePackageLocaleStrings:
      description: Update locale strings for a Package
      required: true
      content:
        application/json:
          schema:
            title: UpdatePackageLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this package in the given locale.
                example: 5-Class Pack
              description:
                type: string
                nullable: true
                description: The localised description for this package in the given locale.
                example: A bundle of 5 classes at a discounted rate.
              meta_title:
                type: string
                nullable: true
                description: The localised meta title for this package in the given locale.
                example: 5-Class Pack | Buy Now
              meta_description:
                type: string
                nullable: true
                description: The localised meta description for this package in the given locale.
                example: Save with our 5-class pack and enjoy flexible booking across our services.
    UpdatePackageItemChoiceLocaleStrings:
      description: Update locale strings for a Package Item Choice
      required: true
      content:
        application/json:
          schema:
            title: UpdatePackageItemChoiceLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this item choice in the given locale.
                example: 60-Minute Treatment
              description:
                type: string
                nullable: true
                description: The localised description for this item choice in the given locale.
                example: Choose any 60-minute treatment from our menu.
    CreateProduct:
      description: The product to create.
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CreateProduct'
    UpdateProduct:
      description: |
        Updates the product.
      content:
        application/json:
          schema:
            title: UpdateProduct
            $ref: '#/components/schemas/UpdateProduct'
    CopyProduct:
      description: |
        Body for copying a `Product`. `name` is required so the new copy
        is distinguishable from the source; everything else is optional
        and overrides the corresponding field on the new copy. Fields not
        listed are inherited from the source unchanged.
      required: true
      content:
        application/json:
          schema:
            title: CopyProduct
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new copy. Plain text only — HTML
                  tags are rejected. Required so the copy is distinguishable
                  from the source in the admin list.
                example: Aromatherapy Body Lotion (200ml)
              external_id:
                type: string
                nullable: true
                description: External identifier for integrations.
                example: ext-prod-moisturiser-200
              currency:
                $ref: '#/components/schemas/properties_currency'
              description:
                type: string
                description: |
                  Long-form product description shown on the shopfront.
                  Markdown rendered.
                example: |
                  A rich, fast-absorbing body lotion blended with calming
                  lavender and chamomile essential oils.
              standard_price:
                type: integer
                nullable: true
                description: |
                  Override the standard price on the copy, in the smallest
                  currency unit (e.g. pence). Defaults to the source's
                  standard price when omitted.
                example: 5000
              offered_online:
                type: boolean
                description: Whether the new copy is bookable via the public shopfront.
              private:
                type: boolean
                description: When true, only customers with the direct link can purchase.
              visibility:
                type: string
                description: |
                  Visibility override for the new copy. `public` shows it
                  to everyone; `hidden` keeps it out of search/browse
                  (still purchasable by direct link); `members_only`
                  restricts to permitted membership-type holders.
                enum:
                  - public
                  - hidden
                  - members_only
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Revenue centre to post sales of this product to. Must be
                  valid for the source product's site.
                example: spa-retail
            required:
              - name
    CreateProductPriceRule:
      description: |
        Body for creating a new `PriceRule` on a `Product`. Only `price` is
        required. Date filters narrow when the rule applies; with neither,
        it's an unconditional baseline.
      required: true
      content:
        application/json:
          schema:
            title: CreateProductPriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: |
                  Price in the smallest currency unit (e.g. pence, cents).
                  `4800` is £48.00 on a GBP site.
                example: 4800
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date this rule applies (inclusive). Defaults to
                  today in the product's timezone when omitted.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date this rule applies (inclusive). When omitted,
                  the rule has no end date.
                example: '2026-08-31'
            required:
              - price
    UpdateProductPriceRule:
      description: |
        Body for updating an existing `PriceRule` on a `Product`. All fields
        optional; omitted fields keep their current values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateProductPriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: Price in the smallest currency unit.
                example: 4800
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
    SuggestDescription:
      content:
        application/json:
          schema:
            title: SuggestDescription
            type: object
            additionalProperties: false
            properties:
              description:
                type: string
                description: A starting point which Trybe Intelligence can use to suggest a better description.
                example: |
                  Relaxing 60-minute massage with essential oils. Feels great.
    UpdateProductLocaleStrings:
      description: Update locale strings for a Product
      required: true
      content:
        application/json:
          schema:
            title: UpdateProductLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this product in the given locale.
                example: Yoga Mat
              description:
                type: string
                nullable: true
                description: The localised description for this product in the given locale.
                example: A non-slip yoga mat suitable for all types of yoga.
    CreateRoom:
      description: |
        Body for creating a new `Room`. `name`, `capacity`, and `site_id`
        are required; everything else is optional. The room is scoped to a
        single site — to offer the same physical space across multiple
        sites you must create one room per site.
      required: true
      content:
        application/json:
          schema:
            title: CreateRoom
            type: object
            additionalProperties: false
            required:
              - name
              - capacity
              - site_id
            properties:
              name:
                type: string
                description: |
                  Display name for the room. Shown to staff in the calendar
                  and admin UI. Plain text only.
                example: Treatment Room 1
              capacity:
                type: integer
                minimum: 1
                description: |
                  How many concurrent bookings the room can host. `1`
                  means exclusive single-occupancy. Multi-guest sharing
                  requires an appointment type with
                  `allocate_multi_capacity_rooms = true`.
                example: 1
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the site this room belongs to. The caller's API
                  key must have access to this site, otherwise the
                  request 422s.
                example: 0193b6e0-3b56-7000-9f50-9d3d5e2c2222
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation ID. Defaults to the caller's
                  primary organisation when omitted.
              use_custom_opening_hours:
                type: boolean
                description: |
                  When true, the room uses its own `availability_rules`
                  instead of the site's opening hours. When false (or
                  omitted), the site's hours are used and
                  `availability_rules` is ignored.
              availability_rules:
                type: array
                description: |
                  Per-day availability windows for the room. Only honoured
                  when `use_custom_opening_hours = true`. Each rule must
                  specify `weekday`, `time_from`, and `time_to`.
                items:
                  title: CreateRoomAvailabilityRule
                  type: object
                  additionalProperties: false
                  required:
                    - weekday
                    - time_from
                    - time_to
                  properties:
                    weekday:
                      type: string
                      description: Day of the week this rule applies to.
                      enum:
                        - monday
                        - tuesday
                        - wednesday
                        - thursday
                        - friday
                        - saturday
                        - sunday
                    time_from:
                      type: string
                      description: Daily start time in 24-hour `HH:MM`.
                      example: '09:00'
                    time_to:
                      type: string
                      description: |
                        Daily end time in 24-hour `HH:MM`. Must be after
                        `time_from`.
                      example: '17:00'
              suitable_for_tags:
                type: array
                description: |
                  Tag IDs the room is suitable for. Used by the
                  availability engine to match rooms against an
                  appointment type's required tags.
                items:
                  type: string
                  format: object-id
              tag_ids:
                type: array
                description: |
                  Free-form tag IDs for reporting and filtering. Distinct
                  from `suitable_for_tags`. Tags must belong to the
                  caller's organisation and apply to rooms.
                items:
                  type: string
                  format: object-id
              zone_ids:
                type: array
                description: |
                  Zone IDs the room belongs to. Zones must exist at the
                  same `site_id`; mismatched zones are rejected with 422.
                items:
                  type: string
                  format: object-id
    UpdateRoom:
      description: |
        Body for updating an existing `Room`. Every field is optional —
        only fields you send are written. To clear the
        `availability_rules`, send an empty array (the server normalises
        that to `null`).
      required: true
      content:
        application/json:
          schema:
            title: UpdateRoom
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: New display name for the room.
                example: Treatment Room 1
              capacity:
                type: integer
                minimum: 1
                description: |
                  New concurrent-bookings capacity. Reducing capacity
                  below the count of active bookings doesn't kick anyone
                  out — existing bookings keep their slot.
                example: 2
              use_custom_opening_hours:
                type: boolean
                description: |
                  Toggle whether the room uses its own
                  `availability_rules` or the site's opening hours.
              availability_rules:
                type: array
                description: |
                  Replace the room's per-day availability windows. Send an
                  empty array to clear (server normalises to `null`).
                items:
                  title: UpdateRoomAvailabilityRule
                  type: object
                  additionalProperties: false
                  required:
                    - weekday
                    - time_from
                    - time_to
                  properties:
                    weekday:
                      type: string
                      enum:
                        - monday
                        - tuesday
                        - wednesday
                        - thursday
                        - friday
                        - saturday
                        - sunday
                    time_from:
                      type: string
                      example: '09:00'
                    time_to:
                      type: string
                      example: '17:00'
              suitable_for_tags:
                type: array
                items:
                  type: string
                  format: object-id
              tag_ids:
                type: array
                items:
                  type: string
                  format: object-id
              zone_ids:
                type: array
                items:
                  type: string
                  format: object-id
    CopyRoom:
      description: |
        Body for copying a `Room`. Every field is optional — fields you
        omit are inherited from the source. Pass `site_id` to copy the
        room to a different site (the caller must have access to both
        sites).
      required: true
      content:
        application/json:
          schema:
            title: CopyRoom
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  New display name. Defaults to the source's name when
                  omitted — be careful, you'll end up with two rooms with
                  the same name.
                example: Treatment Room 2
              capacity:
                type: integer
                minimum: 1
                description: |
                  Override capacity on the new copy. Defaults to the source
                  room's capacity when omitted.
                example: 2
              site_id:
                type: string
                format: uuid
                description: |
                  Override the destination site. Defaults to the source's
                  site. The caller's API key must have access to the
                  chosen site.
              organisation_id:
                type: string
                format: uuid
                description: Override the destination organisation.
              use_custom_opening_hours:
                type: boolean
                description: |
                  When true, the room follows its own opening hours
                  (defined via availability_rules) rather than inheriting
                  the parent site's. Inherited from the source when
                  omitted.
                example: false
              availability_rules:
                type: array
                items:
                  title: CopyRoomAvailabilityRule
                  type: object
                  additionalProperties: false
                  required:
                    - weekday
                    - time_from
                    - time_to
                  properties:
                    weekday:
                      type: string
                      enum:
                        - monday
                        - tuesday
                        - wednesday
                        - thursday
                        - friday
                        - saturday
                        - sunday
                    time_from:
                      type: string
                      example: '09:00'
                    time_to:
                      type: string
                      example: '17:00'
              suitable_for_tags:
                type: array
                items:
                  type: string
                  format: object-id
              tag_ids:
                type: array
                items:
                  type: string
                  format: object-id
              zone_ids:
                type: array
                items:
                  type: string
                  format: object-id
    CreateTableReservationTypeRequest:
      description: Create a new table reservation type.
      content:
        application/json:
          schema:
            title: CreateTableReservationTypeRequest
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                description: |
                  Identifier of the site that owns this reservation type.
                  Table reservation types are scoped per site so each
                  venue can publish its own menus, dining rooms, and
                  capacity rules.
                format: uuid
              name:
                type: string
                description: A name for the table reservation type.
                example: Dinner reservation
              integration_config_id:
                type: string
                format: object-id
                description: |
                  Identifier of the integration config used to relay
                  reservations created for this type into the connected
                  third-party system (e.g. SevenRooms, ResDiary). The
                  config must already be linked to the same site.
              description:
                type: string
                description: A description of the table reservation type.
                example: Enjoy a relaxing meal in our main restaurant.
              external_id:
                type: string
                nullable: true
                description: An external identifier for this offering.
                example: ext-tab-dinner
              product_code:
                type: string
                description: A custom product code for the table reservation type.
                example: DIN
              image_id:
                type: string
                format: uuid
                description: |
                  Media ID of the hero image shown on the storefront
                  reservation page. Upload via
                  [`createMedia`](/endpoints/Media#createMedia) first and
                  pass the returned ID here.
              revenue_centre:
                type: string
                description: The revenue centre to assign revenue to for this offering
                example: restaurant
              customer_reschedule_permitted:
                description: Updated self-reschedule policy for this table reservation type.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which rescheduling is locked.
                example: PT24H
            required:
              - site_id
              - name
    UpdateTableReservationTypeRequest:
      description: Update a table reservation type.
      content:
        application/json:
          schema:
            title: UpdateTableReservationTypeRequest
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: A name for the table reservation type.
                example: Dinner reservation
              integration_config_id:
                type: string
                format: object-id
                description: |
                  Identifier of the integration config used to relay
                  reservations created for this type into the connected
                  third-party system (e.g. SevenRooms, ResDiary). The
                  config must already be linked to the same site.
              description:
                type: string
                description: A description of the table reservation type.
                example: Enjoy a relaxing meal in our main restaurant.
              external_id:
                type: string
                nullable: true
                description: An external identifier for this offering.
                example: ext-tab-dinner
              product_code:
                type: string
                description: A custom product code for the table reservation type.
                example: DIN
              image_id:
                type: string
                format: uuid
                description: |
                  Media ID of the hero image shown on the storefront
                  reservation page. Upload via
                  [`createMedia`](/endpoints/Media#createMedia) first and
                  pass the returned ID here.
              revenue_centre:
                type: string
                description: The revenue centre to assign revenue to for this offering
                example: restaurant
              customer_reschedule_permitted:
                description: Updated self-reschedule policy for this table reservation type.
                $ref: '#/components/schemas/customerReschedulePermitted'
              customer_reschedule_min_duration:
                type: string
                nullable: true
                description: ISO 8601 duration before start at which rescheduling is locked.
                example: PT24H
    CreateTableReservationOptionRequest:
      description: Create a new table reservation option.
      content:
        application/json:
          schema:
            title: CreateTableReservationOptionRequest
            allOf:
              - $ref: '#/components/schemas/UpdateTableReservationOptionRequest-content-application~1json-schema'
    UpdateTableReservationOptionRequest:
      description: Update an existing table reservation option.
      content:
        application/json:
          schema:
            title: UpdateTableReservationOptionRequest
            type: object
            additionalProperties: false
            properties:
              provider_id:
                type: string
                description: The ID of this option with the provider of the table reservation, if applicable.
                example: '1234'
              name:
                type: string
                description: Customer-facing label for this option, shown alongside the reservation type during checkout. Plain text; appears verbatim in confirmation emails and on the POS so keep it concise and unambiguous.
                example: Afternoon tea
              type:
                type: string
                description: An identifier for the type of the option.
                example: promotion
              optional:
                type: boolean
                description: Whether this option may be selected or is included by default.
            required:
              - name
    CreatePractitionerRotaStandalone:
      description: |
        The request body for creating a new `PractitionerRota` via the
        standalone collection. The `practitioner_id` field identifies the
        practitioner the rota belongs to.
      required: true
      content:
        application/json:
          schema:
            title: CreatePractitionerRotaStandalone
            type: object
            additionalProperties: false
            properties:
              practitioner_id:
                type: string
                format: object-id
                description: |
                  Practitioner the new rota applies to. The caller must
                  have `SCHEDULE_MANAGE` (or equivalent) on every site the
                  practitioner works at — otherwise the request is rejected
                  with `403`.
                example: 5dcb47800000000000000010
              start_date:
                type: string
                format: date
                nullable: true
                description: The date from which this rota is active (YYYY-MM-DD).
              end_date:
                type: string
                format: date
                nullable: true
                description: The date on which this rota ends. Omit or pass null for an open-ended rota.
              scheduling_week_interval:
                type: integer
                description: The number of weeks in the rolling schedule cycle.
                example: 2
              availability_rules:
                type: array
                description: The availability rules for this rota.
                items:
                  $ref: '#/components/schemas/PractitionerRotaAvailabilityRule'
            required:
              - practitioner_id
              - scheduling_week_interval
              - availability_rules
    UpdatePractitionerRotaStandalone:
      description: |
        The request body for updating a `PractitionerRota` via the
        standalone collection. The practitioner the rota belongs to
        cannot be changed once the rota is created.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionerRotaStandalone
            type: object
            additionalProperties: false
            properties:
              start_date:
                type: string
                format: date
                nullable: true
                description: The date from which this rota is active (YYYY-MM-DD).
              end_date:
                type: string
                format: date
                nullable: true
                description: The date on which this rota ends. Pass null for an open-ended rota.
              scheduling_week_interval:
                type: integer
                description: The number of weeks in the rolling schedule cycle.
                example: 2
              availability_rules:
                type: array
                description: The availability rules for this rota.
                items:
                  $ref: '#/components/schemas/PractitionerRotaAvailabilityRule'
            required:
              - scheduling_week_interval
              - availability_rules
    CreatePractitionerTag:
      description: |
        Body for creating a new `PractitionerTag`. `name` is required;
        `organisation_id` defaults to the caller's default organisation
        when omitted.
      required: true
      content:
        application/json:
          schema:
            title: CreatePractitionerTag
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new tag. Plain text only. Tag names
                  do not need to be unique within an organisation, but
                  duplicates can make the UI confusing — pick distinct
                  labels where possible.
                example: Senior Therapist
              organisation_id:
                type: string
                format: uuid
                description: |
                  Organisation to attribute the tag to. Defaults to the
                  caller's default organisation when omitted. The caller
                  must belong to the target organisation.
                example: 22222222-2222-2222-2222-222222222222
            required:
              - name
    UpdatePractitionerTag:
      description: |
        Body for updating an existing `PractitionerTag`. Only `name` can
        be changed; tags cannot be moved between organisations.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionerTag
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: New display name for the tag.
                example: Senior Therapist
            required:
              - name
    CreatePractitioner:
      description: |
        Body for creating a new `Practitioner`. `name` and `site_ids` are
        required; everything else is optional. Returns the freshly created
        `Practitioner` so the caller can stash its `id`. Requires the
        `SETTINGS_MANAGE` permission on each site listed in `site_ids`.
      required: true
      content:
        application/json:
          schema:
            title: CreatePractitioner
            type: object
            additionalProperties: false
            required:
              - name
              - site_ids
            properties:
              name:
                type: string
                description: |
                  Display name of the practitioner shown to customers in the
                  booking flow and to staff in the admin UI.
                example: Jane Doe
              site_ids:
                type: array
                description: |
                  One or more site IDs the practitioner works at. Must contain
                  at least one site; the first entry becomes the practitioner's
                  "default" site for zone- and commission-package lookups. The
                  caller's user must be a member of every site listed.
                items:
                  type: string
                  format: uuid
                minItems: 1
                example:
                  - 6f1234567890abcdef123456
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation to attribute this practitioner to. The
                  caller's user must belong to the organisation. Defaults to
                  the caller's primary organisation when omitted.
              tag_ids:
                type: array
                description: |
                  IDs of practitioner tags this person is associated with.
                  Tags must already exist in the caller's primary organisation
                  AND be marked `applies_to: Practitioner` — others are
                  rejected with 422.
                items:
                  type: string
                  format: object-id
              avatar_id:
                type: string
                format: object-id
                nullable: true
                description: |
                  ID of an uploaded `Media` to use as the practitioner's
                  avatar. Shown next to the practitioner's name in the
                  booking widget and admin UI.
                example: 5f1234567890abcdef123456
              signature_id:
                type: string
                format: object-id
                nullable: true
                description: |
                  ID of an uploaded `Media` to use as the practitioner's
                  signature image. Shown on documents and receipts that
                  require a practitioner signature.
              zone_ids:
                type: array
                description: |
                  IDs of zones the practitioner is associated with. Zones must
                  belong to the first site in `site_ids` — zones from other
                  sites are rejected with 422.
                items:
                  type: string
                  format: object-id
              gender:
                type: string
                nullable: true
                description: |
                  Optional gender used by the booking flow to honour customer
                  preferences (e.g. "I'd prefer a female therapist").
                enum:
                  - male
                  - female
                  - non_binary
              registration_number:
                type: string
                nullable: true
                description: |
                  Optional registration or license number for the practitioner.
                  Used to track professional credentials or qualifications.
                example: REG123456
              external_id:
                type: string
                nullable: true
                description: |
                  Optional external identifier for correlating this
                  practitioner with a record in a third-party system.
                example: EXT-001
              commission_package_id:
                type: string
                format: object-id
                nullable: true
                description: |
                  Optional `CommissionPackage` to attach to the practitioner.
                  Drives payroll/commission reporting. Must belong to the
                  first site in `site_ids`.
              user_id:
                type: string
                format: uuid
                nullable: true
                description: |
                  Optional underlying `User` to link to this practitioner.
                  The user must share an organisation with the caller. A
                  given user can be linked to at most one practitioner per
                  site — attempting to reuse a user on the same site is
                  rejected with 422.
    UpdatePractitioner:
      description: |
        Body for updating an existing `Practitioner`. Every field is
        optional; only fields you send are written. Fields you omit retain
        their current values. Requires the `SETTINGS_MANAGE` permission on
        the practitioner's first site.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitioner
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name of the practitioner.
                example: Jane Doe
              email:
                type: string
                format: email
                description: |
                  Optional contact email for the practitioner. Must be unique
                  across all practitioners in the caller's organisations.
                example: jane.doe@example.com
              can_offer_tags:
                type: array
                description: |
                  Free-form list of tag names the practitioner is qualified
                  to deliver. Used by older integrations; new callers should
                  prefer the `tag_ids` association on
                  `practitioners/{id}/appointment-restrictions` instead.
                items:
                  type: string
              tag_ids:
                type: array
                description: |
                  IDs of practitioner tags this person belongs to. Tags must
                  already exist in the caller's primary organisation AND be
                  marked `applies_to: Practitioner`.
                items:
                  type: string
                  format: object-id
              zone_ids:
                type: array
                description: |
                  IDs of zones the practitioner is associated with. Zones
                  must belong to the practitioner's first site.
                items:
                  type: string
                  format: object-id
              scheduling_week_interval_start:
                type: string
                format: date
                description: |
                  ISO 8601 date marking the first week of the practitioner's
                  recurring schedule. Combined with `scheduling_week_interval`
                  to compute multi-week rotas.
                example: '2026-01-05'
              scheduling_week_interval:
                type: integer
                minimum: 1
                maximum: 10
                description: |
                  Length of the recurring schedule in weeks (1-10). `1` means
                  a weekly schedule; `4` means a 4-weekly rota repeating from
                  `scheduling_week_interval_start`.
                example: 1
              avatar_id:
                type: string
                format: object-id
                nullable: true
                description: ID of an uploaded `Media` to use as the practitioner's avatar.
              signature_id:
                type: string
                format: object-id
                nullable: true
                description: ID of an uploaded `Media` to use as the practitioner's signature image.
              order:
                type: integer
                description: |
                  Sort order for the practitioner within the site. Lower
                  numbers sort first. Use `PUT /shop/practitioners/order` to
                  reorder a batch of practitioners in one request.
                example: 3
              gender:
                type: string
                nullable: true
                description: Optional gender; see Create.
                enum:
                  - male
                  - female
                  - non_binary
              registration_number:
                type: string
                nullable: true
                description: |
                  Optional registration or license number for the practitioner.
                example: A123
              external_id:
                type: string
                nullable: true
                description: |
                  Optional external identifier for correlating this
                  practitioner with a record in a third-party system.
                example: EXT-001
              commission_package_id:
                type: string
                format: object-id
                nullable: true
                description: Optional `CommissionPackage` to attach.
              user_id:
                type: string
                format: uuid
                nullable: true
                description: |
                  Optional underlying `User` to link to. The user must share
                  an organisation with the practitioner. A given user can be
                  linked to at most one practitioner per site.
    CopyPractitioner:
      description: |
        Body for copying a `Practitioner`. `name` is required so the new
        copy is distinguishable from the source; other fields are optional
        overrides. Fields not listed (avatar, qualifications, schedule etc.)
        are inherited from the source.
      required: true
      content:
        application/json:
          schema:
            title: CopyPractitioner
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new practitioner copy. Shown to
                  customers in the booking flow and to staff in the admin
                  UI.
                example: Sam Practitioner (Junior)
              can_offer_tags:
                type: array
                description: |
                  Tag names the practitioner can deliver appointments for.
                  The exact set of tags is controlled by
                  `practitioner-tags`; this field references them by name
                  for back-compat with older callers.
                items:
                  type: string
              tag_ids:
                type: array
                description: |
                  IDs of practitioner tags the new copy belongs to. Tags
                  must exist in the caller's organisation AND be marked as
                  `applies_to: Practitioner` — others are rejected with
                  422.
                items:
                  type: string
                  format: object-id
              zone_ids:
                type: array
                description: |
                  IDs of zones the new practitioner is associated with.
                  Zones must belong to the source practitioner's site.
                items:
                  type: string
                  format: object-id
              scheduling_week_interval_start:
                type: string
                format: date
                description: |
                  ISO 8601 date marking the first week of the practitioner's
                  recurring schedule. Used together with
                  `scheduling_week_interval` to compute multi-week rotas.
                example: '2026-01-05'
              scheduling_week_interval:
                type: integer
                minimum: 1
                maximum: 10
                description: |
                  Length of the recurring schedule in weeks (1-10). `1`
                  means a weekly schedule; `4` means a 4-weekly rota
                  repeating cyclically from `scheduling_week_interval_start`.
                example: 1
              avatar_id:
                type: string
                format: object-id
                nullable: true
                description: ID of an uploaded `Media` to use as the practitioner's avatar.
              signature_id:
                type: string
                format: object-id
                nullable: true
                description: ID of an uploaded `Media` to use as the practitioner's signature image.
            required:
              - name
    CreatePractitionerAppointmentRestriction:
      description: |
        Body for creating a new `PractitionerAppointmentRestriction`. The
        combination of `type` and `applies_to_type` determines which other
        fields are required.

        - When `applies_to_type` is `specific`, `appointment_type_ids` is
          required and `category_ids` must be omitted.
        - When `applies_to_type` is `categories`, `category_ids` is
          required and `appointment_type_ids` must be omitted.
        - When `type` is `max_duration`, `max_duration` is required.
      required: true
      content:
        application/json:
          schema:
            title: CreatePractitionerAppointmentRestriction
            type: object
            additionalProperties: false
            properties:
              type:
                type: string
                description: |
                  The kind of restriction. `cannot_offer` blocks matching
                  appointments outright; `max_duration` caps how long they
                  can be.
                enum:
                  - cannot_offer
                  - max_duration
                example: cannot_offer
              applies_to_type:
                type: string
                description: |
                  How the restriction picks which appointment types it
                  applies to. `specific` uses the supplied
                  `appointment_type_ids`; `categories` uses
                  `category_ids`.
                enum:
                  - specific
                  - categories
                example: specific
              appointment_type_ids:
                type: array
                description: |
                  IDs of the appointment types this restriction applies
                  to. Required when `applies_to_type` is `specific`;
                  prohibited when it is `categories`.
                items:
                  type: string
                  format: object-id
                example:
                  - 5e932c0901d210625e3a8766
              category_ids:
                type: array
                description: |
                  IDs of the categories this restriction applies to.
                  Required when `applies_to_type` is `categories`;
                  prohibited when it is `specific`.
                items:
                  type: string
                  format: object-id
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date the restriction takes effect (inclusive),
                  parsed in the practitioner's timezone. Omit or send
                  `null` to apply with no start bound.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date the restriction takes effect (inclusive),
                  parsed in the practitioner's timezone. Omit or send
                  `null` for an open-ended restriction.
                example: '2026-08-31'
              max_duration:
                type: integer
                minimum: 1
                description: |
                  Maximum appointment duration in minutes. Required when
                  `type` is `max_duration`; ignored otherwise.
                example: 60
            required:
              - type
              - applies_to_type
    UpdatePractitionerAppointmentRestriction:
      description: |
        Body for updating an existing
        `PractitionerAppointmentRestriction`. The server runs the same
        validation as on create, so `type` and `applies_to_type` are both
        required and conditional fields (`appointment_type_ids`,
        `category_ids`, `max_duration`) must be sent based on those
        values.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionerAppointmentRestriction
            type: object
            additionalProperties: false
            properties:
              type:
                type: string
                enum:
                  - cannot_offer
                  - max_duration
                description: The kind of restriction. See create for semantics.
                example: max_duration
              applies_to_type:
                type: string
                enum:
                  - specific
                  - categories
                description: How the restriction picks which appointment types it applies to.
                example: categories
              appointment_type_ids:
                type: array
                description: Required when `applies_to_type` is `specific`; prohibited when it is `categories`.
                items:
                  type: string
                  format: object-id
              category_ids:
                type: array
                description: Required when `applies_to_type` is `categories`; prohibited when it is `specific`.
                items:
                  type: string
                  format: object-id
                example:
                  - 5e932c0901d210625e3a8766
              date_from:
                type: string
                format: date
                nullable: true
                description: First date the restriction takes effect (inclusive). `null` clears the start date.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date the restriction takes effect (inclusive). `null` clears the end date.
                example: '2026-08-31'
              max_duration:
                type: integer
                minimum: 1
                description: Required when `type` is `max_duration`.
                example: 90
            required:
              - type
              - applies_to_type
    CreatePractitionerCustomAvailability:
      description: |
        Body for creating a new `PractitionerCustomAvailability` rule.
        `date_time_to` must be strictly after `date_time_from`. When
        `is_available` is `false`, the request fails with a validation
        error if the practitioner already has confirmed appointments or
        sessions inside the window.

        If the new rule sits adjacent to or overlaps an existing rule
        with the same `is_available` value, `room_id`, `category_ids`,
        and `offerings`, the server merges them and returns the resulting
        rule.
      required: true
      content:
        application/json:
          schema:
            title: CreatePractitionerCustomAvailability
            type: object
            additionalProperties: false
            properties:
              date_time_from:
                type: string
                format: date-time
                description: |
                  Start of the window, as an ISO 8601 date-time. Times
                  without an explicit offset are interpreted in the
                  practitioner's timezone.
                example: '2026-06-01T09:00:00+01:00'
              date_time_to:
                type: string
                format: date-time
                description: |
                  End of the window, as an ISO 8601 date-time. Must be
                  after `date_time_from`.
                example: '2026-06-01T17:00:00+01:00'
              is_available:
                type: boolean
                description: |
                  `true` opens an extra working window; `false` blocks
                  bookings (e.g. leave). `false` rules will fail
                  validation if existing confirmed appointments or
                  sessions overlap the window.
                example: false
              offerings:
                type: array
                description: |
                  The offerings the practitioner is assigned to during this
                  window. An empty array (or omitted) means the practitioner
                  is not linked to specific offerings for this window.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
            required:
              - date_time_from
              - date_time_to
              - is_available
    AssignRoomToPractitionerCustomAvailability:
      description: |
        Payload for assigning a room to a practitioner's custom availability
        on a specific date and time range. Pass `room_id: null` to remove a
        room assignment from the targeted segment.
      required: true
      content:
        application/json:
          schema:
            title: AssignRoomToPractitionerCustomAvailability
            type: object
            additionalProperties: false
            properties:
              date:
                type: string
                format: date
                description: The date to target, in YYYY-MM-DD format.
                example: '2026-06-16'
              time_from:
                type: string
                description: Start time of the target range in HH:MM format.
                example: '09:00'
              time_to:
                type: string
                description: End time of the target range in HH:MM format. Must be after `time_from`.
                example: '13:00'
              room_id:
                type: string
                format: object-id
                nullable: true
                description: The room to assign to the target range. Pass null to remove a room assignment.
                example: 5dcb47800000000000000077
              category_ids:
                type: array
                description: Optional category IDs used when carving matching availability segments.
                items:
                  type: string
                  format: object-id
              offerings:
                type: array
                description: |
                  The offerings to assign to the target range. Pass an
                  empty array to remove all offering assignments from the
                  targeted segments. Omitting this field leaves existing
                  offering assignments unchanged.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
            required:
              - date
              - time_from
              - time_to
    UpdatePractitionerCustomAvailability:
      description: |
        Body for updating a `PractitionerCustomAvailability` rule. Every
        field is optional; send only the fields you want to change.
        `date_time_to` must remain strictly after `date_time_from` after
        the update. The merge-on-overlap behaviour from create also
        applies on update.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionerCustomAvailability
            type: object
            additionalProperties: false
            properties:
              date_time_from:
                type: string
                format: date-time
                description: New start of the window. ISO 8601; defaults to the practitioner's timezone if no offset is given.
                example: '2026-06-01T10:00:00+01:00'
              date_time_to:
                type: string
                format: date-time
                description: New end of the window. Must be after `date_time_from`.
                example: '2026-06-01T18:00:00+01:00'
              is_available:
                type: boolean
                description: Whether the practitioner is bookable during the window.
                example: true
              offerings:
                type: array
                description: |
                  The offerings the practitioner is assigned to during this
                  window. An empty array (or omitted) means the practitioner
                  is not linked to specific offerings for this window.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
    CreatePractitionerRotaRequest:
      description: The request body for creating a new `PractitionerRota`.
      required: true
      content:
        application/json:
          schema:
            title: CreatePractitionerRotaRequest
            type: object
            additionalProperties: false
            properties:
              practitioner_id:
                type: string
                format: object-id
                description: |
                  Identifier of the practitioner this rota applies to.
                  Must match the `practitionerId` in the URL; included in
                  the body so the rota is self-describing on writeback to
                  integrations and audit logs.
              start_date:
                type: string
                format: date
                nullable: true
                description: The date from which this rota is active (YYYY-MM-DD).
              end_date:
                type: string
                format: date
                nullable: true
                description: The date on which this rota ends. Omit or pass null for an open-ended rota.
              scheduling_week_interval:
                type: integer
                description: The number of weeks in the rolling schedule cycle.
                example: 2
              availability_rules:
                type: array
                description: The availability rules for this rota.
                items:
                  $ref: '#/components/schemas/PractitionerRotaAvailabilityRule'
            required:
              - practitioner_id
              - scheduling_week_interval
              - availability_rules
    UpdatePractitionerRotaRequest:
      description: The request body for updating a `PractitionerRota`.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionerRotaRequest
            type: object
            additionalProperties: false
            properties:
              start_date:
                type: string
                format: date
                nullable: true
                description: The date from which this rota is active (YYYY-MM-DD).
              end_date:
                type: string
                format: date
                nullable: true
                description: The date on which this rota ends. Pass null for an open-ended rota.
              scheduling_week_interval:
                type: integer
                description: The number of weeks in the rolling schedule cycle.
                example: 2
              availability_rules:
                type: array
                description: The availability rules for this rota.
                items:
                  $ref: '#/components/schemas/PractitionerRotaAvailabilityRule'
            required:
              - scheduling_week_interval
              - availability_rules
    CreateRoomTag:
      description: |
        Body for creating a new `RoomTag`. `name` is required;
        `organisation_id` defaults to the caller's default organisation
        when omitted.
      required: true
      content:
        application/json:
          schema:
            title: CreateRoomTag
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new tag. Plain text only. Tag names
                  do not need to be unique within an organisation, but
                  duplicates can make the UI confusing — pick distinct
                  labels where possible.
                example: Couples Room
              organisation_id:
                type: string
                format: uuid
                description: |
                  Organisation to attribute the tag to. Defaults to the
                  caller's default organisation when omitted. The caller
                  must belong to the target organisation.
                example: 22222222-2222-2222-2222-222222222222
            required:
              - name
    UpdateRoomTag:
      description: |
        Body for updating an existing `RoomTag`. Only `name` can be
        changed; tags cannot be moved between organisations.
      required: true
      content:
        application/json:
          schema:
            title: UpdateRoomTag
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: New display name for the tag.
                example: Couples Room
            required:
              - name
    CreateZone:
      description: |
        Body for creating a new `Zone`. `name` and `site_id` are required.
        `organisation_id` defaults to the caller's organisation when
        omitted.
      required: true
      content:
        application/json:
          schema:
            title: CreateZone
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new zone. Plain text only. Zone
                  names do not need to be unique within a site, but
                  duplicates can make the UI confusing — pick distinct
                  labels where possible.
                example: Pool Deck
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the site to create this zone under. The caller's
                  API key must have access to the site and the
                  `SETTINGS_MANAGE` permission on it.
                example: 11111111-1111-1111-1111-111111111111
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation to attribute the zone to. Defaults
                  to the caller's primary organisation when omitted.
                example: 22222222-2222-2222-2222-222222222222
            required:
              - name
              - site_id
    UpdateZone:
      description: |
        Body for updating an existing `Zone`. Only `name` can be changed;
        zones cannot be moved between sites or organisations.
      required: true
      content:
        application/json:
          schema:
            title: UpdateZone
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: New display name for the zone.
                example: Pool Deck
            required:
              - name
    TestTaxConfiguration:
      content:
        application/json:
          schema:
            title: TestTaxConfiguration
            type: object
            additionalProperties: false
            properties:
              amount:
                $ref: '#/components/schemas/amount'
              date:
                $ref: '#/components/schemas/date'
    CreateVisitTypeRequest:
      content:
        application/json:
          schema:
            title: CreateVisitTypeRequest
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: A name to identify this visit configuration, for internal use.
                example: Spa Weekend
              description:
                type: string
                description: A description of this visit configuration, for internal use.
                example: To be offered to guests staying in December.
              offerings:
                type: array
                description: An array of offerings which each guest can choose from. Each guest may choose one of the following.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
            required:
              - name
    UpdateVisitTypeRequest:
      content:
        application/json:
          schema:
            title: UpdateVisitTypeRequest
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: A name to identify this visit configuration, for internal use.
                example: Spa Weekend
              description:
                type: string
                description: A description of this visit configuration, for internal use.
                example: To be offered to guests staying in December.
              offerings:
                type: array
                description: An array of offerings which each guest can choose from. Each guest may choose one of the following.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              email_settings:
                title: EmailSettings
                additionalProperties: false
                type: object
                description: Email settings associated with this visit type.
                properties:
                  creation_email_message:
                    type: string
                    description: Message sent when a visit is created.
                    example: Your visit has been created.
                    nullable: true
                  reminder_emails_enabled:
                    type: boolean
                    description: Flag to indicate if reminder emails are enabled.
                    example: true
                    nullable: true
                  reminder_emails_message:
                    type: string
                    description: Reminder message for the upcoming visit.
                    example: This is a reminder for your upcoming visit.
                    nullable: true
                  reminder_emails_time:
                    type: string
                    description: Time to send the reminder emails.
                    example: '09:00'
                    nullable: true
                  reminder_emails_days_ahead:
                    type: integer
                    description: Number of days ahead to send the reminder email.
                    example: 2
                    nullable: true
              integration_settings:
                $ref: '#/components/schemas/IntegrationSettings'
              rate_codes:
                type: array
                description: An array of unique rate codes associated with this visit type. Each code must be unique across all visit types.
                items:
                  type: string
                  example: RATE100
                nullable: true
    CreateVoucherType:
      description: |
        Body for creating a new `VoucherType`. `name` is the only strictly
        required field; the rest have sensible defaults. The shape and
        semantics of several fields depend on `amount_type`:

        - `amount_type=cash` — sets up a gift voucher worth a fixed cash
          amount (e.g. a £50 gift card). The cash-only fields
          `amount`, `customisable_amount`, and `partially_redeemable` apply;
          `valid_weekdays`, `invalid_date_set_ids`, `valid_offerings` and
          `invalid_offerings` are ignored and forced to `null` server-side.
        - `amount_type=discount_to_zero` — sets up a "spend-on-one-thing"
          voucher (e.g. a free 60-minute massage). The discount-only fields
          `valid_weekdays`, `invalid_date_set_ids`, `valid_offerings` and
          `invalid_offerings` apply; `amount`, `customisable_amount` and
          `partially_redeemable` are ignored.

        The new voucher type is created under the site identified by the
        `site_id` query parameter and the caller's primary organisation. The
        caller must hold `SETTINGS_MANAGE` on that site.
      required: true
      content:
        application/json:
          schema:
            title: CreateVoucherType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Customer-facing display name for the voucher type. Shown in
                  the shopfront, the gift-voucher email, and the admin UI.
                  Plain text.
                example: £50 Gift Voucher
              description:
                type: string
                nullable: true
                description: |
                  Long-form description of what the voucher type is for. Shown
                  on the voucher's shopfront page.
                example: A £50 gift voucher to spend on any treatment or retail item at our spa.
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map this voucher type to an
                  external POS or PMS catalogue. Free-form string; uniqueness
                  is not enforced server-side.
                example: VOU-GIFT-50
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this voucher type. Free-form.
                example: ext-gift-50
              image_id:
                type: string
                nullable: true
                description: |
                  ID of an uploaded `Media` to use as the cover image on the
                  voucher type's shopfront page and in the gift-voucher email.
                  Must reference a media item belonging to the caller's
                  organisation.
                example: 5f1234567890abcdef123456
              recipient_message:
                type: string
                nullable: true
                description: |
                  Default message included in the gift-voucher email sent to
                  the recipient. The customer can override this at purchase
                  time. HTML is accepted but stripped down to the site's
                  allowed-tag list server-side.
                example: |
                  <p>Enjoy your gift! Spend it on anything you like at our spa.</p>
              hide_redemption_instructions:
                type: boolean
                description: |
                  When `true`, the "Use your voucher" button and accompanying
                  instructions are omitted from the gift-voucher email. Use
                  this for vouchers redeemed outside of Trybe (e.g. free items
                  not listed in the shopfront) to avoid sending guests to a
                  dead-end lookup page. Defaults to `false`.
                example: false
              amount_type:
                type: string
                description: |
                  Determines whether this voucher type is a fixed-amount gift
                  card (`cash`) or a single-offering discount-to-zero voucher
                  (`discount_to_zero`). Drives which other fields are honoured
                  — see the body description for details.
                enum:
                  - cash
                  - discount_to_zero
                example: cash
              amount:
                type: integer
                description: |
                  The cash value of the voucher in the smallest currency unit
                  (e.g. pence/cents). **Only relevant when
                  `amount_type=cash`.** Ignored for `discount_to_zero`.
                example: 5000
              customisable_amount:
                type: boolean
                description: |
                  When true, the cashier (or customer at checkout) can override
                  the voucher's value at sale time — useful for "any amount"
                  gift cards. **Only relevant when `amount_type=cash`;**
                  dropped from the payload for `discount_to_zero`.
                example: false
              customer_customisable_amount:
                type: boolean
                description: |
                  When true, customers can enter their own amount when purchasing this
                  voucher online. Only relevant when `amount_type=cash`.
                example: false
              minimum_custom_amount:
                type: integer
                nullable: true
                minimum: 500
                description: |
                  The minimum amount (in the voucher's minor currency unit, e.g. pence)
                  that a customer may enter when `customer_customisable_amount` is `true`.
                  When omitted or `null`, the system-wide minimum of 500 applies. Must be
                  >= 500. **Only relevant when `amount_type=cash`.**
                example: 1000
              partially_redeemable:
                type: boolean
                description: |
                  When true, vouchers of this type can be redeemed in multiple
                  transactions until the balance is exhausted. When false,
                  the full value must be spent in one go and any remainder is
                  forfeited. **Only relevant when `amount_type=cash`.**
                example: true
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this voucher type, in the smallest
                  currency unit (e.g. pence). Optional at create time —
                  voucher types can be created without a standard price and
                  have one configured later.
                example: 5000
              quantity:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  For `discount_to_zero` vouchers only. When set to a value
                  greater than 1, an issued code can be redeemed this many
                  times before it is considered fully used. `null`, omitted, or
                  `1` means single-use. **Ignored for `cash` vouchers.**
                example: 7
              per_use_value:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  For multi-use `discount_to_zero` vouchers only. The fixed amount
                  (in the voucher's minor currency unit) posted to the ledger per
                  redemption, and the maximum this voucher will cover per use.
                  Items priced above this value require partial payment from the
                  customer. **Required when `quantity` is greater than 1.**
                example: 5000
              valid_weekdays:
                type: array
                nullable: true
                description: |
                  Lowercase weekday names the voucher may be redeemed on.
                  **Only relevant when `amount_type=discount_to_zero`;**
                  forced to `null` for `cash`.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - monday
                  - tuesday
                  - wednesday
                  - thursday
                  - friday
              invalid_date_set_ids:
                type: array
                nullable: true
                description: |
                  IDs of date sets (e.g. bank holidays, blackout periods) on
                  which the voucher may **not** be redeemed. **Only relevant
                  when `amount_type=discount_to_zero`;** forced to `null` for
                  `cash`. Each ID must belong to the caller's organisation.
                items:
                  type: string
                  format: object-id
              valid_offerings:
                type: array
                nullable: true
                description: |
                  Allowlist of offerings the voucher may be redeemed against.
                  When set, the voucher is only valid for these offerings.
                  **Only relevant when `amount_type=discount_to_zero`;**
                  forced to `null` for `cash`.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              invalid_offerings:
                type: array
                nullable: true
                description: |
                  Denylist of offerings the voucher may **not** be redeemed
                  against. Used when `valid_offerings` is empty to express
                  "any offering except these". **Only relevant when
                  `amount_type=discount_to_zero`.**
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              default_validity_interval:
                type: string
                nullable: true
                description: |
                  Default duration a sold voucher is valid for, as an ISO 8601
                  duration. The voucher's expiry is computed as `purchased_at
                  + default_validity_interval`. Examples: `P1Y` = 1 year,
                  `P6M` = 6 months, `P30D` = 30 days.
                example: P1Y
              offered_online:
                type: boolean
                description: |
                  When true, the voucher type can be purchased via the public
                  shopfront. When false, it's sellable only via the admin UI.
                example: true
              private:
                type: boolean
                description: |
                  When true, the voucher type is reachable only via a direct
                  link — it doesn't appear on category pages and isn't indexed
                  by search engines.
                example: false
              visibility:
                $ref: '#/components/schemas/visibility'
              members_only:
                type: boolean
                description: |
                  When true, only customers with an active membership can
                  purchase this voucher type. Combine with
                  `permitted_membership_type_ids` to restrict further to
                  specific tiers.
                example: false
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership-type UUIDs whose active members are allowed to
                  purchase this voucher type. Only relevant when
                  `members_only=true`. Membership types from outside the
                  site's brand are silently filtered out server-side.
                items:
                  type: string
                  format: uuid
              category_ids:
                type: array
                description: |
                  Voucher-category IDs this voucher type belongs to. Used for
                  shopfront grouping. Each ID must reference a category on the
                  voucher type's site.
                items:
                  type: string
                  format: object-id
              currency:
                allOf:
                  - $ref: '#/components/schemas/properties_currency'
                description: |
                  The ISO-4217 currency code (lowercase) the voucher's
                  `amount` is expressed in. Must be a currency supported by
                  the site.
                example: gbp
            required:
              - name
    UpdateVoucherType:
      description: |
        Body for updating an existing `VoucherType`. The validator is the
        same as create — `name` is required, the rest are optional. Note
        that the controller calls `Eloquent::update()` with the validated
        payload, so omitted fields **retain their current values**; pass an
        explicit `null` to clear nullable fields.

        The `amount_type`-based field rules apply on every update:

        - For `amount_type=cash`, the discount-only fields
          (`valid_weekdays`, `invalid_date_set_ids`, `valid_offerings`,
          `invalid_offerings`) are forced to `null`.
        - For `amount_type=discount_to_zero`, the cash-only fields
          (`amount`, `customisable_amount`, `partially_redeemable`) are
          dropped from the payload.

        Sending `category_ids: []` explicitly clears the category list.
        Requires `SETTINGS_MANAGE` on the voucher type's site.
      required: true
      content:
        application/json:
          schema:
            title: UpdateVoucherType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Customer-facing display name. Plain text.
                example: £50 Gift Voucher
              description:
                type: string
                nullable: true
                description: Long-form description shown on the voucher's shopfront page.
                example: A £50 gift voucher to spend on any treatment.
              product_code:
                type: string
                nullable: true
                description: External POS/PMS product code.
                example: VOU-GIFT-50
              external_id:
                type: string
                nullable: true
                description: External identifier for integrations.
                example: ext-gift-50
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` to use as the cover image.
                example: 5f1234567890abcdef123456
              recipient_message:
                type: string
                nullable: true
                description: |
                  Default message included in the gift-voucher email. HTML is
                  stripped to the site's allowed-tag list.
                example: |
                  <p>Enjoy your gift!</p>
              hide_redemption_instructions:
                type: boolean
                description: |
                  When `true`, the "Use your voucher" button and accompanying
                  instructions are omitted from the gift-voucher email. Use
                  this for vouchers redeemed outside of Trybe to avoid sending
                  guests to a dead-end lookup page.
                example: false
              amount_type:
                type: string
                description: |
                  Switches the voucher between a fixed cash-value gift card
                  (`cash`) and a single-offering discount-to-zero voucher
                  (`discount_to_zero`). Drives which other fields are
                  honoured.
                enum:
                  - cash
                  - discount_to_zero
              amount:
                type: integer
                description: |
                  Cash value in the smallest currency unit. **Only relevant
                  when `amount_type=cash`.**
                example: 5000
              customisable_amount:
                type: boolean
                description: |
                  When true, the value can be overridden at sale time. **Only
                  relevant when `amount_type=cash`.**
              customer_customisable_amount:
                type: boolean
                description: |
                  When true, customers can enter their own amount when purchasing
                  this voucher online. **Only relevant when `amount_type=cash`.**
              minimum_custom_amount:
                type: integer
                nullable: true
                minimum: 500
                description: |
                  The minimum amount (in the voucher's minor currency unit, e.g. pence)
                  that a customer may enter when `customer_customisable_amount` is `true`.
                  Pass `null` to revert to the system-wide minimum (500). Must be >= 500.
                  **Only relevant when `amount_type=cash`.**
                example: 1000
              partially_redeemable:
                type: boolean
                description: |
                  When true, the voucher can be redeemed across multiple
                  transactions. **Only relevant when `amount_type=cash`.**
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this voucher type, in the smallest
                  currency unit (e.g. pence). Pass `null` to clear a
                  previously-set standard price.
                example: 5000
              quantity:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  For `discount_to_zero` vouchers only. When set to a value
                  greater than 1, an issued code can be redeemed this many
                  times before it is considered fully used. Pass `null` or `1`
                  to revert to single-use. **Ignored for `cash` vouchers.**
                example: 7
              per_use_value:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  For multi-use `discount_to_zero` vouchers only. The fixed amount
                  (in the voucher's minor currency unit) posted to the ledger per
                  redemption, and the maximum this voucher will cover per use.
                  Items priced above this value require partial payment from the
                  customer. **Required when `quantity` is greater than 1. Pass
                  `null` to clear.**
                example: 5000
              valid_weekdays:
                type: array
                nullable: true
                description: |
                  Lowercase weekday names the voucher is valid on. **Only
                  relevant when `amount_type=discount_to_zero`.**
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
              invalid_date_set_ids:
                type: array
                nullable: true
                description: |
                  Date-set IDs the voucher is **not** valid on. **Only
                  relevant when `amount_type=discount_to_zero`.**
                items:
                  type: string
                  format: object-id
              valid_offerings:
                type: array
                nullable: true
                description: |
                  Allowlist of offerings the voucher may be redeemed against.
                  **Only relevant when `amount_type=discount_to_zero`.**
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              invalid_offerings:
                type: array
                nullable: true
                description: |
                  Denylist of offerings the voucher may not be redeemed
                  against. **Only relevant when `amount_type=discount_to_zero`.**
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              default_validity_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration a sold voucher is valid for after
                  purchase. e.g. `P1Y` = 1 year.
                example: P1Y
              offered_online:
                type: boolean
                description: Whether the voucher type is sellable via the public shopfront.
              private:
                type: boolean
                description: When true, the voucher type is reachable only via direct link.
              visibility:
                $ref: '#/components/schemas/visibility'
              members_only:
                type: boolean
                description: When true, only customers with an active membership can purchase.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership-type UUIDs whose active members are allowed to
                  purchase. Only relevant when `members_only=true`.
                items:
                  type: string
                  format: uuid
              category_ids:
                type: array
                description: |
                  Voucher-category IDs this voucher type belongs to. Sending
                  `[]` clears the existing categories.
                items:
                  type: string
                  format: object-id
              currency:
                allOf:
                  - $ref: '#/components/schemas/properties_currency'
                description: ISO-4217 currency code in lowercase. Must be supported by the site.
                example: gbp
            required:
              - name
    UpdateVoucherTypeLocaleStrings:
      description: Update locale strings for a VoucherType
      required: true
      content:
        application/json:
          schema:
            title: UpdateVoucherTypeLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this voucher type in the given locale.
                example: Gift Voucher
              description:
                type: string
                nullable: true
                description: The localised description for this voucher type in the given locale.
                example: A gift voucher redeemable against any service.
    CreateVoucherTypeAvailabilityRule:
      description: |
        Body for creating a new `AvailabilityRule` on a `VoucherType`.
        Availability rules govern when vouchers of this type can be
        redeemed against bookings: any `is_available: false` rule blocks
        redemptions during its window, overriding any `true` rules for
        the same period.

        Both `date_from` and `date_to` are optional. When omitted, the
        rule defaults to starting today (in the voucher type's
        timezone) with no end date.
      required: true
      content:
        application/json:
          schema:
            title: CreateVoucherTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: |
                  `true` opens redemption windows; `false` closes them.
                  `false` rules override `true` rules for the same
                  period.
                example: false
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date the rule applies (inclusive), in the
                  voucher type's timezone. Defaults to today when
                  omitted.
                example: '2026-12-20'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date the rule applies (inclusive). Must be on or
                  after `date_from`. Omit for an open-ended rule.
                example: '2027-01-02'
            required:
              - is_available
    UpdateVoucherTypeAvailabilityRule:
      description: |
        Body for updating an existing `AvailabilityRule` on a
        `VoucherType`. The server runs the same validation as on create,
        so `is_available` is required and any supplied dates must be in
        `YYYY-MM-DD` form with `date_to` on or after `date_from`.
      required: true
      content:
        application/json:
          schema:
            title: UpdateVoucherTypeAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: Whether the window is bookable for voucher redemption. `false` overrides `true`.
                example: true
              date_from:
                type: string
                format: date
                nullable: true
                description: First date the rule applies (inclusive).
                example: '2026-12-20'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date the rule applies (inclusive). Must be on or after `date_from`.
                example: '2027-01-02'
            required:
              - is_available
    CopyVoucherType:
      description: |
        Body for copying a `VoucherType`. `name` is required so the new
        copy is distinguishable from the source; every other field is
        optional and overrides the corresponding field on the copy. Fields
        not listed are inherited from the source unchanged.

        The `amount_type` conditional rules apply just as on create:

        - For `amount_type=cash`, the discount-only fields are forced to
          `null` on the copy.
        - For `amount_type=discount_to_zero`, the cash-only fields are
          dropped from the payload.
      required: true
      content:
        application/json:
          schema:
            title: CopyVoucherType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the new copy. Required so the copy is distinguishable from the source.
                example: £100 Gift Voucher
              description:
                type: string
                nullable: true
                description: Override the long-form description on the copy. Defaults to the source's description when omitted.
                example: A £100 gift voucher to spend on any treatment.
              product_code:
                type: string
                nullable: true
                description: Override the POS/PMS product code. Defaults to the source's value.
                example: VOU-GIFT-100
              external_id:
                type: string
                nullable: true
                description: |
                  Override the external identifier on the copy. Defaults to
                  the source's value; consider setting this explicitly so
                  integrations don't see two offerings with the same external
                  id.
                example: ext-gift-100
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` to use as the cover image. Defaults to the source's image.
                example: 5f1234567890abcdef123456
              recipient_message:
                type: string
                nullable: true
                description: |
                  Override the gift-voucher recipient message. HTML is
                  stripped to the site's allowed-tag list.
                example: |
                  <p>Enjoy your £100 voucher!</p>
              hide_redemption_instructions:
                type: boolean
                description: |
                  Override whether the "Use your voucher" button and
                  instructions are omitted from the gift-voucher email on the
                  copy. Defaults to the source's value when omitted.
                example: false
              amount_type:
                type: string
                description: |
                  Override the voucher amount type on the copy. Switching this
                  between `cash` and `discount_to_zero` clears the fields
                  that don't apply to the new type.
                enum:
                  - cash
                  - discount_to_zero
              amount:
                type: integer
                description: |
                  Override the cash value (smallest currency unit) on the
                  copy. **Only relevant when `amount_type=cash`.**
                example: 10000
              customisable_amount:
                type: boolean
                description: |
                  Override whether the value can be customised at sale time.
                  **Only relevant when `amount_type=cash`.**
              partially_redeemable:
                type: boolean
                description: |
                  Override whether the copy can be partially redeemed. **Only
                  relevant when `amount_type=cash`.**
              standard_price:
                type: integer
                nullable: true
                description: |
                  Override the standard price on the copy, in the smallest
                  currency unit (e.g. pence). Defaults to the source's
                  standard price when omitted.
                example: 5000
              quantity:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Override the number of redemptions allowed per issued code.
                  When greater than 1, a single code can be redeemed this many
                  times. Pass `null` or `1` for single-use. **Only relevant when
                  `amount_type=discount_to_zero`.**
                example: 7
              per_use_value:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Override the fixed per-redemption value on the copy. The fixed
                  amount (in the voucher's minor currency unit) posted to the
                  ledger per redemption, and the maximum the voucher covers per
                  use. **Required when `quantity` is greater than 1. Pass `null`
                  to clear.**
                example: 5000
              valid_weekdays:
                type: array
                nullable: true
                description: |
                  Override the lowercase weekday allowlist. **Only relevant
                  when `amount_type=discount_to_zero`.**
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
              invalid_date_set_ids:
                type: array
                nullable: true
                description: |
                  Override the denylist of date-set IDs the copy is invalid
                  on. **Only relevant when `amount_type=discount_to_zero`.**
                items:
                  type: string
                  format: object-id
              valid_offerings:
                type: array
                nullable: true
                description: |
                  Override the allowlist of offerings the copy may be
                  redeemed against. **Only relevant when
                  `amount_type=discount_to_zero`.**
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              invalid_offerings:
                type: array
                nullable: true
                description: |
                  Override the denylist of offerings the copy may not be
                  redeemed against. **Only relevant when
                  `amount_type=discount_to_zero`.**
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              default_validity_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration a sold voucher of this copy is valid for.
                  Override the source's default. e.g. `P1Y` = 1 year.
                example: P1Y
              offered_online:
                type: boolean
                description: Whether the copy is sellable via the public shopfront.
              private:
                type: boolean
                description: When true, the copy is reachable only via direct link.
              visibility:
                $ref: '#/components/schemas/visibility'
              members_only:
                type: boolean
                description: When true, only members can purchase the copy.
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Membership-type UUIDs whose active members can purchase the
                  copy. Only relevant when `members_only=true`.
                items:
                  type: string
                  format: uuid
              category_ids:
                type: array
                description: |
                  Override the voucher-category memberships on the copy.
                  Each ID must reference a category on the voucher type's
                  site.
                items:
                  type: string
                  format: object-id
              currency:
                allOf:
                  - $ref: '#/components/schemas/properties_currency'
                description: ISO-4217 currency code in lowercase. Must be supported by the site.
                example: gbp
            required:
              - name
    UpdateVoucher:
      description: |
        Body for `updateVoucher`. Every field is optional; pass only the
        fields you want to change. Use `valid_offerings` to replace the
        full list of redeemable offerings in one call; use the dedicated
        `POST /shop/vouchers/{voucherId}/offerings` and
        `DELETE /shop/vouchers/{voucherId}/offerings/{offeringId}` endpoints
        to add or remove a single offering at a time.
      required: true
      content:
        application/json:
          schema:
            title: UpdateVoucherRequest
            type: object
            additionalProperties: false
            properties:
              valid_offerings:
                type: array
                description: |
                  Replacement allowlist of offerings the voucher may be
                  redeemed against. Pass an empty array to clear the
                  allowlist (making the voucher redeemable against any
                  offering).
                items:
                  $ref: '#/components/schemas/UpdateVoucherValidOffering'
              valid_weekdays:
                type: array
                description: |
                  Lowercase weekday names the voucher may be redeemed on.
                  Empty (or omitted) means "any weekday".
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - monday
                  - tuesday
                  - wednesday
                  - thursday
                  - friday
              invalid_date_set_ids:
                type: array
                description: |
                  IDs of date sets on which the voucher may **not** be
                  redeemed. Each ID must reference a date set on the
                  caller's organisation.
                items:
                  type: string
                  format: object-id
                example:
                  - 65f0a1b2c3d4e5f6a7b8c9aa
    CreateVoucherValidOffering:
      description: |
        Body for `createVoucherValidOffering`. Adds a single offering to the
        voucher's `valid_offerings` allowlist. The full updated `Voucher`
        is returned in the response.
      required: true
      content:
        application/json:
          schema:
            title: CreateVoucherValidOfferingRequest
            type: object
            additionalProperties: false
            properties:
              offering_type:
                type: string
                description: |
                  Snake-case type of the offering being added (e.g.
                  `appointment`, `session`, `package`).
                enum:
                  - appointment
                  - area_booking
                  - course
                  - hotel_room_reservation
                  - package
                  - product
                  - session
                  - table_reservation
                example: session
              offering_id:
                type: string
                description: |
                  Identifier of the offering to add to this voucher's
                  valid-offerings list. Paired with `offering_type` to
                  disambiguate which collection the ID belongs to.
                example: 65f0a1b2c3d4e5f6a7b8c9d4
            required:
              - offering_type
              - offering_id
    CreateCustomer:
      content:
        application/json:
          schema:
            title: CreateCustomer
            type: object
            additionalProperties: false
            properties:
              site_id:
                $ref: '#/components/schemas/site_id'
              first_name:
                $ref: '#/components/schemas/first_name'
              last_name:
                $ref: '#/components/schemas/last_name'
              phone:
                $ref: '#/components/schemas/phone'
              dob:
                $ref: '#/components/schemas/dob'
              email:
                $ref: '#/components/schemas/email'
              password:
                $ref: '#/components/schemas/password'
              marketing_preference_ids:
                type: array
                description: An array of marketing preference IDs to opt the customer in to
                items:
                  type: string
                  format: mongo-id
              external_ref:
                $ref: '#/components/schemas/external_ref'
              guestline_ref:
                $ref: '#/components/schemas/guestline_ref'
              preferred_locale:
                $ref: '#/components/schemas/preferred_locale'
            required:
              - site_id
    UpdateCustomer:
      content:
        application/json:
          schema:
            type: object
            title: UpdateCustomer
            additionalProperties: false
            properties:
              first_name:
                $ref: '#/components/schemas/first_name'
              last_name:
                $ref: '#/components/schemas/last_name'
              phone:
                $ref: '#/components/schemas/phone'
              dob:
                $ref: '#/components/schemas/dob'
              password:
                $ref: '#/components/schemas/password'
              external_ref:
                $ref: '#/components/schemas/external_ref'
              preferred_locale:
                $ref: '#/components/schemas/preferred_locale'
    UpdateAssociatedBarcode:
      content:
        application/json:
          schema:
            title: UpdateAssociatedBarcode
            type: object
            additionalProperties: false
            properties:
              payment_method_id:
                type: string
                format: uuid
                description: |
                  Identifier of the customer's saved payment method to
                  attach to this wearable/access barcode. The barcode can
                  then be used to pay at any in-resort POS via "charge to
                  card on file". Pass `null` to clear the attachment.
                nullable: true
              order_id:
                type: string
                format: object-id
                description: |
                  Identifier of an in-progress order to attach to this
                  barcode. Lets a scanned barcode pull up the linked order
                  at the POS (for example to keep adding items during a
                  spa visit). Pass `null` to detach.
                nullable: true
              expires_at:
                type: string
                format: date-time
                description: The expiry date to set for the associated barcode.
                nullable: true
    CreateMarketingPreference:
      description: Create a marketing preference
      content:
        application/json:
          schema:
            title: CreateMarketingPreference
            type: object
            additionalProperties: false
            properties:
              text:
                type: string
                description: The text of the marketing preference
                example: I want to receive emails about special offers
              locale:
                type: string
                description: |
                  The locale this marketing preference's text is written in. A marketing
                  preference only ever has one language; to offer the same preference in
                  multiple languages, create a separate marketing preference per locale.

                  This must be one of the platform's supported locales, which can be retrieved using the [`listMetaSupportedLocales`](/endpoints/Meta#listMetaSupportedLocales) endpoint.
                example: en
              site_id:
                type: string
                description: |
                  Optional site that this marketing preference applies to.
                  When set, only customers signing up at this site are
                  offered the opt-in; leave blank to apply the preference
                  across every site in the organisation.
                format: uuid
              organisation_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation that owns this marketing
                  preference. Preferences are inherited by every site in
                  the organisation unless `site_id` narrows the scope.
            required:
              - text
              - locale
              - organisation_id
    UpdateMarketingPreference:
      description: Update a marketing preference
      content:
        application/json:
          schema:
            title: UpdateMarketingPreference
            type: object
            additionalProperties: false
            properties:
              text:
                type: string
                description: The text of the marketing preference
                example: I want to receive emails about special offers
            required:
              - text
    CreateSiteMarketingPreference:
      description: Enable a marketing preference for a site
      content:
        application/json:
          schema:
            title: CreateSiteMarketingPreference
            type: object
            additionalProperties: false
            properties:
              marketing_preference_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation-level marketing preference
                  to enable at this site. After enablement, customers
                  signing up at the site are offered this opt-in checkbox
                  alongside any preferences already enabled.
            required:
              - marketing_preference_id
    CreateSiteMembershipType:
      description: Enable a membership type for a site
      content:
        application/json:
          schema:
            title: CreateSiteMembershipType
            type: object
            additionalProperties: false
            properties:
              membership_type_id:
                type: string
                format: uuid
                description: |
                  Identifier of the brand-level membership tier to enable
                  at this site. After enablement, customers can purchase
                  this tier from the site's storefront and existing members
                  of the tier can use it at this site.
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site the membership tier should be
                  enabled at. Must match the `siteId` in the URL; provided
                  in the body to make the request self-describing for
                  audit logs.
            required:
              - membership_type_id
              - site_id
    CreateInventoryBrand:
      content:
        application/json:
          schema:
            title: CreateInventoryBrandRequest
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site that owns this inventory brand.
                  Brands are scoped per site, so the API key must have access
                  to this site. Must belong to the supplied `organisation_id`.
              organisation_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation this brand sits under.
                  Used for cross-site reporting and to enforce that the
                  referenced `site_id` belongs to the same organisation.
              name:
                type: string
                description: |
                  Human-readable name of the inventory brand, shown in the
                  inventory admin UI and on supplier order forms.
                  Trimmed; must be 1-120 characters and not contain HTML.
                example: L'Oréal
            required:
              - name
              - site_id
              - organisation_id
    UpdateInventoryBrand:
      description: Update an Inventory Brand
      content:
        application/json:
          schema:
            title: UpdateInventoryBrand
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Human-readable name of the inventory brand, shown in the
                  inventory admin UI and on supplier order forms.
                  Trimmed; must be 1-120 characters and not contain HTML.
                example: L'Oréal
    CreateInventoryCategory:
      content:
        application/json:
          schema:
            title: CreateInventoryCategoryRequest
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site that owns this inventory category.
                  Categories are scoped per site so each site can maintain
                  its own taxonomy. Must belong to `organisation_id`.
              organisation_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation this category sits under.
                  Used for cross-site reporting and authorisation; the
                  supplied `site_id` must belong to this organisation.
              name:
                type: string
                description: |
                  Human-readable name for the inventory category, used to
                  group related inventory products in the admin UI and on
                  reports. Trimmed; 1-120 characters.
                example: Massage oils
            required:
              - name
              - site_id
              - organisation_id
    ReorderInventoryCategories:
      content:
        application/json:
          schema:
            title: ReorderInventoryCategories
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site whose inventory categories are
                  being reordered. All IDs in `category_ids` must belong
                  to this site; the caller's API key must have access to it.
              category_ids:
                type: array
                description: |
                  The inventory category IDs in the desired display order. Each
                  category's position in this array is stored as its order.
                items:
                  type: string
                  format: uuid
            required:
              - site_id
              - category_ids
    UpdateInventoryCategory:
      description: Update an Inventory Category
      content:
        application/json:
          schema:
            title: UpdateInventoryCategory
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Human-readable name for the inventory category, used to
                  group related inventory products in the admin UI and on
                  reports. Trimmed; 1-120 characters.
                example: Massage oils
    CreateSupplier:
      description: Create a Supplier
      content:
        application/json:
          schema:
            title: CreateSupplier
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Trading name of the inventory supplier, shown on purchase
                  orders and supplier reports. Trimmed; 1-120 characters,
                  must not contain HTML.
                example: Elemis
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site that owns this supplier record.
                  Supplier records are scoped per site so each site can
                  maintain its own supplier list, terms, and contact info.
            required:
              - name
              - site_id
    UpdateSupplier:
      description: Update a Supplier
      content:
        application/json:
          schema:
            title: UpdateSupplier
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Trading name of the inventory supplier, shown on purchase
                  orders and supplier reports. Trimmed; 1-120 characters,
                  must not contain HTML.
                example: Elemis
              email:
                type: string
                description: An email address for the supplier.
                example: orders@example.com
                nullable: true
              phone:
                type: string
                description: A phone number for the supplier.
                example: +44 20 8012 3456
                nullable: true
              address_1:
                type: string
                description: The first line of the supplier's address.
                example: Unit E, Dominion Way
                nullable: true
              address_2:
                type: string
                description: The second line of the supplier's address.
                example: Rustington
                nullable: true
              city:
                type: string
                description: The city part of the supplier's address.
                example: Littlehampton
                nullable: true
              county:
                type: string
                description: The county part of the supplier's address.
                example: West Sussex
                nullable: true
              country:
                type: string
                description: The country part of the supplier's address.
                example: UK
                nullable: true
              postcode:
                type: string
                description: The ZIP or postal code part of the supplier's address.
                example: BN16 3HQ
                nullable: true
    CopySupplier:
      description: Copy a Supplier
      content:
        application/json:
          schema:
            type: object
            title: CopySupplier
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Name to give the duplicated supplier. Typically the source
                  supplier's name with a "(copy)" suffix. Trimmed;
                  1-120 characters and must not contain HTML.
                example: Elemis
            required:
              - name
    CreateInventoryProduct:
      description: Create an Inventory Product
      content:
        application/json:
          schema:
            title: CreateInventoryProduct
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the inventory product, shown to staff in
                  the stock admin UI and on purchase orders, stocktake
                  sheets, and reports. Trimmed; 1-120 characters and must
                  not contain HTML.
                example: Blissful Body Butter
              brand_id:
                type: string
                format: uuid
                description: |
                  Identifier of the inventory brand this product is sold
                  under. Used for filtering and reporting. Pass `null` if
                  the product is unbranded; the brand must belong to the
                  same site as `site_id`.
                nullable: true
              category_id:
                type: string
                format: uuid
                description: |
                  Identifier of the inventory category this product is
                  classified under. Used for filtering, reporting, and
                  report grouping. Pass `null` for uncategorised products;
                  the category must belong to the same site as `site_id`.
                nullable: true
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site that owns this inventory product.
                  Stock levels, suppliers, and adjustments are all scoped
                  per site; the caller's API key must have access to it.
            required:
              - name
              - brand_id
              - category_id
              - site_id
    UpdateInventoryProduct:
      description: Update an Inventory Product
      content:
        application/json:
          schema:
            title: UpdateInventoryProduct
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the inventory product, shown to staff in
                  the stock admin UI and on purchase orders, stocktake
                  sheets, and reports. Trimmed; 1-120 characters and must
                  not contain HTML.
                example: Blissful Body Butter
              description:
                type: string
                description: |
                  Long-form description of the inventory product, shown on
                  the product detail screen. Plain text; line breaks are
                  preserved. Pass `null` to clear an existing description.
                example: A rich, creamy body butter which deeply nourishes the skin, with essential oils.
                nullable: true
              sku:
                type: string
                description: The stock keeping unit (SKU) for the inventory product.
                example: BB-001
                nullable: true
              barcode:
                type: string
                description: The barcode for the inventory product.
                example: '0123456789'
                nullable: true
              reorder_level:
                type: integer
                description: The quantity of this inventory product which should be reordered.
                example: 10
                nullable: true
              brand_id:
                type: string
                format: uuid
                description: |
                  Identifier of the inventory brand this product is sold
                  under. Used for filtering and reporting. Pass `null` if
                  the product is unbranded; the brand must belong to the
                  same site as the product.
                nullable: true
              category_id:
                type: string
                format: uuid
                description: |
                  Identifier of the inventory category this product is
                  classified under. Used for filtering, reporting, and
                  report grouping. Pass `null` for uncategorised products;
                  the category must belong to the same site as the product.
                nullable: true
    CopyInventoryProduct:
      description: Copy an Inventory Product
      content:
        application/json:
          schema:
            type: object
            title: CopyInventoryProduct
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Name to give the duplicated inventory product. Typically
                  the source product's name with a "(copy)" suffix. Trimmed;
                  1-120 characters and must not contain HTML.
                example: Blissful Body Butter
            required:
              - name
    CreateInventoryProductAdjustment:
      content:
        application/json:
          schema:
            title: CreateInventoryProductAdjustment
            type: object
            additionalProperties: false
            properties:
              quantity:
                type: number
                description: The amount of the adjustment, which may be positive or negative.
                example: 10.5
              reason_code:
                type: string
                description: The preset reason code for the adjustment.
                example: Professional Use
              reason_description:
                type: string
                description: A free-text description of the reason for the adjustment.
                example: Stock used for professional use
                nullable: true
              location_id:
                type: string
                format: uuid
                description: |
                  Identifier of the stock location the adjustment is recorded
                  against. For positive adjustments stock is added at this
                  location; for negative adjustments stock is removed from it.
                  Pass `null` if the site uses a single, default location.
                nullable: true
            required:
              - quantity
              - reason_code
              - reason_description
              - location_id
    UpdateInventoryProductSupplier:
      description: Update an Inventory Product Supplier
      content:
        application/json:
          schema:
            title: UpdateInventoryProductSupplier
            type: object
            additionalProperties: false
            properties:
              order_quantity:
                type: integer
                description: The default quantity of the inventory product to be ordered from this supplier.
                example: 10
                nullable: true
              unit_price:
                type: integer
                description: The unit price of the inventory product in the lowest denomination for this product's currency.
                example: 200
            required:
              - order_quantity
              - unit_price
    CreateInventoryProductSupplier:
      content:
        application/json:
          schema:
            title: CreateInventoryProductSupplierRequest
            type: object
            additionalProperties: false
            properties:
              supplier_id:
                type: string
                format: uuid
                description: |
                  Identifier of the supplier this product is purchased from.
                  Used when generating purchase orders and on supplier reports.
                  The supplier must belong to the same site as the product.
              order_quantity:
                type: integer
                description: The default quantity of the inventory product to be ordered from this supplier.
                example: 10
                nullable: true
              unit_price:
                type: integer
                description: The unit price of the inventory product in the lowest denomination for this product's currency.
                example: 200
            required:
              - supplier_id
              - order_quantity
              - unit_price
    CreateInventoryOrder:
      description: Create an Inventory Order
      content:
        application/json:
          schema:
            title: CreateInventoryOrder
            type: object
            additionalProperties: false
            properties:
              purchase_order_number:
                type: string
                description: The purchase order number for this inventory order.
                example: PO123
                nullable: true
              supplier_id:
                type: string
                format: uuid
                description: |
                  Identifier of the supplier this order will be sent to.
                  The supplier must belong to the same site as `site_id`;
                  order line items can only reference inventory products
                  that are linked to this supplier.
              supplier_email:
                type: string
                description: The email address of the supplier for this inventory order.
                example: orders@example.com
                nullable: true
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this inventory order is placed for.
                  Goods will be received against this site's stock, and only
                  users with access to this site can view or modify the order.
            required:
              - purchase_order_number
              - supplier_id
              - supplier_email
              - site_id
    UpdateInventoryOrder:
      description: Update an Inventory Order
      content:
        application/json:
          schema:
            title: UpdateInventoryOrder
            type: object
            additionalProperties: false
            properties:
              purchase_order_number:
                type: string
                description: The purchase order number for this inventory order.
                example: PO123
              supplier_email:
                type: string
                description: The email address of the supplier for this inventory order.
                example: orders@example.com
    CreateInventoryOrderItem:
      description: Create an Inventory Order Item
      content:
        application/json:
          schema:
            title: CreateInventoryOrderItemRequest
            type: object
            additionalProperties: false
            properties:
              product_id:
                type: string
                format: uuid
                description: |
                  Identifier of the inventory product to add as a line item.
                  The product must belong to the same site as the order's
                  `site_id` and must be linked to the order's supplier.
              quantity:
                type: integer
                description: The quantity of the inventory product being ordered.
                example: 10
              unit_price:
                type: integer
                description: The unit price of the inventory product in the lowest denomination for the product's currency.
                example: 200
            required:
              - product_id
              - quantity
              - unit_price
    UpdateInventoryOrderItem:
      description: Update an Inventory Order Item
      content:
        application/json:
          schema:
            title: UpdateInventoryOrderItem
            type: object
            additionalProperties: false
            properties:
              quantity:
                type: integer
                description: The quantity of the inventory product being ordered.
                example: 10
              unit_price:
                type: integer
                description: The unit price of the inventory product in the lowest denomination for the product's currency.
                example: 200
    CreateStockTake:
      description: Create a Stocktake
      content:
        application/json:
          schema:
            title: CreateStockTakeRequest
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site the stocktake is being performed at.
                  All items counted in this stocktake must belong to this
                  site; the caller's API key must have access to it.
              location_id:
                type: string
                format: uuid
                description: |
                  Identifier of the stock location being counted. Counts are
                  recorded against this location, and any variance found
                  creates adjustments at this location only.
              description:
                type: string
                description: |
                  Free-text label shown in the admin UI and on stocktake
                  reports, used to distinguish this stocktake from others
                  (e.g. "Quarterly retail count Q1 2024"). 1-255 characters.
                example: Stocktake started on 01/06/2024
            required:
              - description
              - site_id
              - location_id
    UpdateStockTake:
      description: Update a Stocktake
      content:
        application/json:
          schema:
            title: UpdateStockTake
            type: object
            additionalProperties: false
            properties:
              description:
                type: string
                description: |
                  Free-text label shown in the admin UI and on stocktake
                  reports, used to distinguish this stocktake from others
                  (e.g. "Quarterly retail count Q1 2024"). 1-255 characters.
                example: Stocktake started on 01/06/2024
    UpdateStockTakeItem:
      description: Update a Stocktake Item
      content:
        application/json:
          schema:
            title: UpdateStockTakeItem
            type: object
            additionalProperties: false
            properties:
              counted_quantity:
                type: number
                description: The quantity counted for this stocktake item.
                example: 50.5
                nullable: true
    ConfirmAppointmentEnquiryRequest:
      content:
        application/json:
          schema:
            title: ConfirmAppointmentEnquiry
            type: object
            additionalProperties: false
            properties:
              time:
                type: string
                description: The date and time that the appointment should start.
                example: '2026-06-15T10:00:00Z'
            required:
              - time
    CreateCoupon:
      description: Create a coupon
      content:
        application/json:
          schema:
            title: CreateCouponRequest
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this coupon is valid at. Coupons
                  are scoped per site so each location can issue and
                  redeem its own promotional codes. The caller's API key
                  must have access to this site.
              name:
                type: string
                description: |
                  Internal label for the coupon, shown to staff in the
                  admin UI and on reports. Not customer-facing; codes
                  issued from this coupon use a separate redemption code.
                  1-120 characters.
                example: Test coupon
              description:
                type: string
                description: A string to describe the coupon
                example: This coupon is a test
                nullable: true
              valid_weekdays:
                type: array
                description: An array of weekdays which this coupon is available for use
                items:
                  type: string
                  description: A weekday, in English, lowercase, and not shortened
                  example: monday
              invalid_date_set_ids:
                type: array
                description: An array of IDs of `DateSet`s describing when this coupon is _not_ valid. The DateSet must belong to the same organisation as the coupon.
                items:
                  type: string
                  format: object-id
                  description: The ID of the date set
              default_validity_interval:
                type: string
                description: The default duration this coupon is valid for, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                example: P1Y
                nullable: true
              default_multi_use:
                type: boolean
                description: The default for whether a code created from this coupon may be used multiple times
                example: true
              for_lead_booker_only:
                type: boolean
                description: Whether this coupon can only be used by the lead booker of a booking
                example: false
              max_uses:
                type: integer
                nullable: true
                description: The maximum number of times this coupon can be used within the specified max uses period
                example: 2
              max_uses_period:
                type: string
                nullable: true
                enum:
                  - P1D
                  - P1W
                  - P1M
                  - P1Y
                description: |
                  The time period for usage limits when max_uses is set.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                  P1D = daily limit, P1W = weekly limit, P1M = monthly limit, P1Y = yearly limit
              redemption_type:
                type: string
                description: The method that this coupon may be redeemed.
                enum:
                  - manual
                  - programmatic
            required:
              - name
              - site_id
    UpdateCoupon:
      description: Update a coupon
      content:
        application/json:
          schema:
            title: UpdateCoupon
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the coupon, shown to staff in the
                  admin UI and on reports. Not customer-facing; codes
                  issued from this coupon use a separate redemption code.
                  1-120 characters.
                example: Test coupon
              description:
                type: string
                description: A string to describe the coupon
                example: This coupon is a test
                nullable: true
              valid_weekdays:
                type: array
                description: An array of weekdays which this coupon is available for use
                items:
                  type: string
                  description: A weekday, in English, lowercase, and not shortened
                  example: monday
              invalid_date_set_ids:
                type: array
                description: An array of IDs of `DateSet`s describing when this coupon is _not_ valid. The DateSet must belong to the same organisation as the coupon.
                items:
                  type: string
                  format: object-id
                  description: The ID of the date set
              default_validity_interval:
                type: string
                description: The default duration this coupon is valid for, as an ISO8601 string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                example: P1Y
                nullable: true
              default_multi_use:
                type: boolean
                description: The default for whether a code created from this coupon may be used multiple times
                example: true
              for_lead_booker_only:
                type: boolean
                description: Whether this coupon can only be used by the lead booker of a booking
                example: false
              max_uses:
                type: integer
                nullable: true
                description: The maximum number of times this coupon can be used within the specified max uses period
                example: 2
              max_uses_period:
                type: string
                nullable: true
                enum:
                  - P1D
                  - P1W
                  - P1M
                  - P1Y
                description: |
                  The time period for usage limits when max_uses is set.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                  P1D = daily limit, P1W = weekly limit, P1M = monthly limit, P1Y = yearly limit
              redemption_type:
                type: string
                description: The method that this coupon may be redeemed.
                enum:
                  - manual
                  - programmatic
            required:
              - name
    UpdateCouponLocaleStrings:
      description: Update locale strings for a Coupon
      required: true
      content:
        application/json:
          schema:
            title: UpdateCouponLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this coupon in the given locale.
                example: Free 30 minute massage
              description:
                type: string
                nullable: true
                description: The localised description for this coupon in the given locale.
                example: Enjoy a free 30 minute massage as a thanks for being a loyal member
    CreateCouponCode:
      description: |
        Body for creating a new `CouponCode`. All fields optional — pass
        only what you need:
        - `code` to set a specific redemption string (omit for auto-gen)
        - `valid_from_date` / `valid_to_date` to time-limit the code
        - `multi_use` to allow multiple redemptions
        - `customer_credit_id` + `customer_id` to pre-allocate to a
          specific customer's credit

        Requires the `SETTINGS_MANAGE` permission on the coupon's site.
        Returns 422 if `code` is already in use under the same coupon.
      required: true
      content:
        application/json:
          schema:
            title: CreateCouponCode
            type: object
            additionalProperties: false
            properties:
              code:
                type: string
                nullable: true
                description: The redemption code customers type. Omitted = auto-generated. Must be unique within the coupon.
                example: SUMMER2026
              valid_from_date:
                type: string
                format: date-time
                nullable: true
                description: ISO 8601 timestamp from which the code is redeemable. Null = valid immediately.
                example: '2026-06-01T00:00:00Z'
              valid_to_date:
                type: string
                format: date-time
                nullable: true
                description: |
                  ISO 8601 timestamp after which the code expires. Must be
                  after `valid_from_date` if both are set.
                example: '2026-08-31T23:59:59Z'
              multi_use:
                type: boolean
                nullable: true
                description: |
                  When true, the code can be redeemed multiple times (once
                  per customer). When false / omitted, the code is
                  single-use.
                example: false
              customer_credit_id:
                type: string
                nullable: true
                description: |
                  If set, pre-allocates the code to a specific
                  `CustomerCredit`. Requires `customer_id`.
                example: 5f1234567890abcdef123456
              customer_id:
                type: string
                format: uuid
                nullable: true
                description: |
                  ID of the customer this code is pre-allocated to.
                  **Required** when `customer_credit_id` is set.
                example: 11111111-1111-1111-1111-111111111111
              revenue:
                type: integer
                nullable: true
                description: Override revenue in the smallest currency unit. Null = use the coupon's default.
                example: 5000
    CreateOfferingDiscount:
      description: Create an offering discount for a coupon
      content:
        application/json:
          schema:
            title: CreateOfferingDiscount
            type: object
            additionalProperties: false
            properties:
              offerings:
                type: array
                description: An array of offerings which this discount applies to
                items:
                  $ref: '#/components/schemas/schemas_Offering'
              discount_type:
                type: string
                enum:
                  - fixed_amount
                  - percentage
                description: The type of discount to be applied
              fixed_amount:
                type: integer
                description: The amount of discount to apply as an integer of the smallest unit of currency.
                example: 50
              percentage:
                type: integer
                description: The percentage of discount to apply
                example: 10
            required:
              - offerings
              - discount_type
    UpdateOfferingDiscount:
      description: Update an offering discount for a coupon
      content:
        application/json:
          schema:
            title: UpdateOfferingDiscount
            type: object
            additionalProperties: false
            properties:
              offerings:
                type: array
                description: An array of offerings which this discount applies to
                items:
                  $ref: '#/components/schemas/schemas_Offering'
              discount_type:
                type: string
                enum:
                  - fixed_amount
                  - percentage
                description: The type of discount to be applied
              fixed_amount:
                type: integer
                description: The amount of discount to apply as an integer of the smallest unit of currency.
                example: 50
              percentage:
                type: integer
                description: The percentage of discount to apply
                example: 10
    CreateOrder:
      required: true
      content:
        application/json:
          schema:
            title: CreateOrder
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  The site the order belongs to. Must be a site the calling
                  user has permission to manage reservations for.
                example: 5e932c0901d210625e3a8766
              status:
                type: string
                enum:
                  - new
                  - in_progress
                default: new
                description: |
                  The initial status of the order. `new` is the default; use
                  `in_progress` to flag the order as actively being worked on
                  by a member of staff (this distinction is useful for live
                  dashboards and concurrency reporting).
              customer_id:
                type: string
                description: |
                  Optional ID of the customer to attach to the order at
                  creation time. If omitted, the order starts unassociated
                  and a customer can be attached later via
                  `POST /shop/orders/{orderId}/customer`.
                nullable: true
                example: 5f1a83b9d52d5c2c8b8b4567
              external_ref:
                type: string
                description: |
                  A free-form reference from the calling system — for example
                  a PMS reservation code. Stored verbatim on the order; not
                  interpreted by Trybe.
                example: PMS-12345
              external_ids:
                type: array
                description: |
                  Structured external identifiers to attach to the order. Each
                  entry maps an `ExternalIdType` (looked up by `key`) to a
                  `value`. The `key` must reference an external ID type that
                  exists for the site (or applies to all sites) and is scoped
                  to the `Basket` model.
                items:
                  type: object
                  additionalProperties: false
                  title: CreateOrderExternalId
                  properties:
                    key:
                      type: string
                      description: The external ID type key.
                      example: pms_id
                    value:
                      type: string
                      nullable: true
                      description: The external ID value.
                      example: id_abc123
                  required:
                    - key
              partner_id:
                type: string
                nullable: true
                description: |
                  Registered partner that originated this order. Used for
                  reporting and revenue allocation when orders arrive via a
                  third-party booking partner; must match one of the
                  configured `PartnerConfig` IDs on this organisation.
                example: spafinder
              sales_channel_id:
                type: string
                nullable: true
                description: |
                  The sales channel to attribute the order to. Must reference
                  a sales channel that belongs to the order's organisation.
                example: 5f1a83b9d52d5c2c8b8b4569
            required:
              - site_id
    UpdateOrder:
      required: true
      content:
        application/json:
          schema:
            title: UpdateOrder
            type: object
            additionalProperties: false
            properties:
              customer_id:
                type: string
                nullable: true
                description: |
                  Attach or detach a customer. Pass a customer ID to set the
                  order's customer; pass `null` to remove the current
                  customer. The customer must belong to the same brand as
                  the order's site.
                example: 5f1a83b9d52d5c2c8b8b4567
              sales_channel_id:
                type: string
                nullable: true
                description: The sales channel to attribute the order to.
                example: 5f1a83b9d52d5c2c8b8b4569
              first_name:
                type: string
                description: |
                  First name to record against the order. When set, this also
                  copies through to the lead-booker guest (if one exists) so
                  the order header and the lead guest stay in sync.
                example: Jane
              last_name:
                type: string
                description: Last name to record against the order.
                example: Doe
              email:
                type: string
                format: email
                description: |
                  Email address to record against the order. Must be a
                  syntactically valid address.
                example: jane@example.com
              phone:
                type: string
                nullable: true
                description: |
                  International phone number for the order. Validated and
                  normalised against the site's country code; stored in
                  E.164 format.
                example: '+447700900123'
              integration_config_id:
                type: string
                nullable: true
                description: |
                  Optional reference to an `IntegrationConfig` that scopes
                  this order to a specific integration on the site (for
                  example a PMS connector). Must reference a config that
                  belongs to the same site.
                example: 5f1a83b9d52d5c2c8b8b4571
              stage:
                type: string
                description: |
                  The current basket/order stage. Stages model the
                  user-facing checkout flow (e.g. `customer_details`,
                  `payment`, `confirmation`) and are surfaced to operators.
                  When the only field supplied is `stage`, the order is
                  updated as a lightweight stage transition without running
                  the full update pipeline.
                example: payment
              external_ref:
                type: string
                description: |
                  Free-form reference from the calling system. Stored
                  verbatim on the order.
                example: PMS-12345
              metadata:
                type: object
                additionalProperties:
                  type: string
                  nullable: true
                  maxLength: 1000
                description: |
                  Arbitrary string-to-string metadata to merge into the
                  order. Keys map to string values up to 1,000 characters;
                  passing `null` for a value removes that key. Existing
                  metadata not mentioned in the request is left in place
                  (merge semantics, not replace).
              special_requests:
                type: string
                nullable: true
                description: |
                  Operator-facing notes captured against the order. Only
                  writable by users with the `SETTINGS_MANAGE` permission;
                  omitted from the request body for everyone else.
                example: Quiet room requested.
    PrintPosReceiptForOrder:
      description: Print a POS receipt for an order
      content:
        application/json:
          schema:
            title: PrintPosReceiptForOrder
            type: object
            additionalProperties: false
            properties:
              esc_pos_connector_id:
                type: string
                format: uuid
                description: |
                  Identifier of the
                  [`EscPosConnector`](/endpoints/EscPosConnectors) (receipt
                  printer) to send the rendered receipt to. The connector
                  must belong to the same site as the order.
              guest_input_fields:
                title: GuestInputFields
                description: |
                  The fields to include on the receipt for the guest to fill out.
                additionalProperties: false
                type: object
                properties:
                  name:
                    type: boolean
                    description: |
                      Whether to include a space for the guest to write their name on the receipt.
                      If `true`, the field will be included on the printed receipt.
                  signature:
                    type: boolean
                    description: |
                      Whether to include a space for the guest to sign on the receipt.
                      If `true`, the field will be included on the printed receipt.
                  room_number:
                    type: boolean
                    description: |
                      Whether to include a space for the guest to write their room number on the receipt.
                      If `true`, the field will be included on the printed receipt.
                  gratuity:
                    type: boolean
                    description: |
                      Whether to include a space for the guest to write a gratuity amount on the receipt.
                      If `true`, the field will be included on the printed receipt.
            required:
              - esc_pos_connector_id
    CreateOrderPayment:
      required: true
      content:
        application/json:
          schema:
            title: CreateOrderPayment
            type: object
            additionalProperties: false
            properties:
              amount:
                description: |
                  The amount of the payment, expressed in the lowest denomination of
                  the order's currency (e.g. pennies for `GBP`, cents for `USD`).
                  Must be greater than zero unless `capture_method` is `on_demand`
                  and the request is being used to store a payment method for later
                  charging — in which case `0` is also accepted.
                type: integer
                example: 10000
              capture_method:
                description: |
                  When the payment amount should be captured. Use `automatic` for
                  an immediate capture (the default for most manual entries) or
                  `on_demand` when storing a payment method to be charged later.
                type: string
                nullable: true
                example: automatic
              details_source:
                description: |
                  How the payment method will be supplied — for example
                  `pay_by_link` for a hosted checkout link, or `terminal` for an
                  in-person card terminal.
                type: string
                nullable: true
                example: pay_by_link
              processor_data:
                description: |
                  An optional dictionary of processor-specific data. For
                  `on_demand` payments this can include
                  `save_payment_method: true` to persist the payment method
                  against the customer for future use.
                type: object
                additionalProperties: true
            required:
              - amount
    PostingRoomToOrder:
      description: |
        The request body you need to send to attach/detach a posting room to an order.
      content:
        application/json:
          schema:
            title: PostingRoomToOrder
            type: object
            additionalProperties: false
            properties:
              posting_room_data:
                type: object
                additionalProperties: true
                description: |
                  Free-form key/value bag identifying the PMS folio that
                  charges from this order should be posted to. The exact
                  shape depends on the PMS in use (e.g. Opera, Cloudbeds);
                  Trybe forwards the data verbatim to the integration. Use
                  `null` to detach a previously-attached posting room.
                example:
                  G#: 2081111
                  RN: '9500'
            required:
              - posting_room_data
    ApplyDiscountToOrder:
      description: Apply a discount to an order
      content:
        application/json:
          schema:
            title: ApplyDiscountToOrder
            type: object
            additionalProperties: false
            properties:
              discount_type_code:
                type: string
                description: |
                  The code for the [`DiscountType`](/endpoints/DiscountTypes).
                  If the code exists, the discount will be applied. If not, an error will be returned.
                example: SUMMER23
              discount_amount:
                type: integer
                description: |
                  The value of the discount to be applied when a [`DiscountType`](/endpoints/DiscountTypes) is applied.
                  If this is for a customisable in-app discount type, this will be able to be changed before being applied.
                example: 15
              amount_type:
                type: string
                description: |
                  The type of discount. For a promo code, this will always be a percentage.
                example: percentage
                enum:
                  - monetary
                  - percentage
              reason_code:
                type: string
                description: |
                  The code for the reason the discount was applied.
                example: coupon
                enum:
                  - coupon
                  - general
                  - predefined
                  - voucher_difference
            required:
              - discount_type_code
              - discount_amount
    SendOrderEmail:
      description: |
        The body required to send an email to the customer for an order. The
        `type` is a string identifier that selects which mailable template to
        render — for example `BookingConfirmation` or `BookingReminder`.
      content:
        application/json:
          schema:
            title: SendOrderEmail
            type: object
            additionalProperties: false
            required:
              - type
            properties:
              type:
                type: string
                description: |
                  The mailable type to send. This selects the underlying template;
                  available types depend on the organisation's configured mailables.
                example: BookingConfirmation
              content:
                type: string
                description: |
                  Optional custom message body to inject into the template. HTML is
                  not permitted — submit plain text only.
                example: Looking forward to welcoming you on Saturday!
              params:
                type: object
                additionalProperties: true
                description: |
                  Additional template parameters to pass through to the mailable —
                  the available keys depend on the chosen `type`.
    PreviewOrderEmail:
      description: |
        The body required to render a preview of an email for an order without
        actually sending it.
      content:
        application/json:
          schema:
            title: PreviewOrderEmail
            type: object
            additionalProperties: false
            required:
              - type
            properties:
              type:
                type: string
                description: The mailable type to preview.
                example: BookingConfirmation
              content:
                type: string
                description: |
                  Optional custom message body to inject into the template. HTML is
                  not permitted — submit plain text only.
                example: Looking forward to welcoming you on Saturday!
              params:
                type: object
                additionalProperties: true
                description: |
                  Additional template parameters to pass through to the mailable —
                  the available keys depend on the chosen `type`.
    UpdateOrderExternalIds:
      description: Update an order's external IDs
      content:
        application/json:
          schema:
            type: object
            title: UpdateOrderExternalIds
            additionalProperties: false
            properties:
              external_ids:
                type: array
                items:
                  type: object
                  title: UpdateOrderExternalId
                  additionalProperties: false
                  properties:
                    key:
                      type: string
                      description: The key of the ID.
                      example: pms_id
                    value:
                      type: integer
                      description: The value of the ID for this order
                      example: pms_123
                  required:
                    - key
                    - value
    CreateOrderGuest:
      description: |
        The body required to add a new guest to an order.

        Whether `name` or the `first_name`/`last_name` pair is required depends on the
        site's `separate_name_values_enforced` setting:

        - If the site separates names, supply both `first_name` and `last_name`.
        - Otherwise, supply `name` as a single string (e.g. `"Jane Doe"`).

        The first guest added to an empty order is automatically marked as the
        lead booker unless `is_lead_booker` is explicitly provided.
      content:
        application/json:
          schema:
            title: CreateOrderGuest
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  The guest's full name. Used when the site does not enforce separate
                  first/last name fields. Optional if `first_name`/`last_name` are
                  provided, if the guest is the lead booker, or if `customer_id` is set.
                example: Jane Doe
              first_name:
                type: string
                description: |
                  The guest's first name. Required when the site enforces separate
                  first/last name fields.
                example: Jane
              last_name:
                type: string
                description: |
                  The guest's last name. Required when the site enforces separate
                  first/last name fields.
                example: Doe
              customer_id:
                type: string
                format: uuid
                description: |
                  Identifier of an existing `Customer` to link this guest to.
                  When provided, the guest's name and email are inherited
                  from the customer record. Omit to create a guest-only
                  entry without a linked customer account.
                example: 5ed2b95f72823c4f98419f20
              is_lead_booker:
                type: boolean
                description: |
                  Whether this guest is the lead booker for the order. Defaults to
                  `true` when this is the first guest on the order, otherwise `false`.
                example: true
    UpdateOrderGuest:
      description: |
        The body required to update an existing guest on an order. When linking the
        guest to a `Customer` via `customer_id`, the guest's name and email are
        overwritten with the customer record's values.
      content:
        application/json:
          schema:
            title: UpdateOrderGuest
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  The guest's full name. Required if `first_name` and `last_name`
                  are not provided.
                example: Jane Doe
              first_name:
                type: string
                description: |
                  The guest's first name. Required when the site enforces separate
                  first/last name fields; otherwise required if `name` is not provided.
                example: Jane
              last_name:
                type: string
                description: |
                  The guest's last name. Required when the site enforces separate
                  first/last name fields; otherwise required if `name` is not provided.
                example: Doe
              customer_id:
                type: string
                format: uuid
                description: |
                  Identifier of an existing `Customer` to link this guest
                  to. The customer must belong to the same brand as the
                  order's site; cross-brand links are rejected with 422.
                example: 5ed2b95f72823c4f98419f20
    CreateOrderItem:
      description: Create an order item.
      content:
        application/json:
          schema:
            title: CreateOrderItem
            type: object
            additionalProperties: false
            properties:
              offering_type:
                $ref: '#/components/schemas/OfferingType'
              offering_id:
                type: string
                description: |
                  Identifier of the offering to add as a line item, paired
                  with `offering_type` to disambiguate which collection
                  the ID belongs to (e.g. `appointment`, `course`, `retail
                  product`). The offering must be sellable at the order's
                  site and currently within its on-sale window.
                example: 5f1234567890abcdef123456
              sold_by:
                type: object
                title: CreateOrderItemSoldBy
                description: The entity selling the offering.
                additionalProperties: false
                properties:
                  id:
                    type: string
                    description: The ID of the entity selling the offering.
                  type:
                    type: string
                    description: The type of the entity selling the offering.
                required:
                  - id
                  - type
              quantity:
                type: integer
                minimum: 1
                description: The quantity of the offering to add to the order.
                example: 1
              guest_ids:
                type: array
                description: A list of guest IDs must be passed if you are not passing `guests`.
                items:
                  type: string
              guests:
                type: array
                description: A list of guest objects must be passed if you are not passing `guest_ids`.
                items:
                  oneOf:
                    - type: object
                      title: CreateOrderItemGuestExistingId
                      additionalProperties: false
                      properties:
                        id:
                          type: string
                      required:
                        - id
                    - type: object
                      title: CreateOrderItemGuestLeadBooker
                      additionalProperties: false
                      properties:
                        is_lead_booker:
                          type: boolean
                      required:
                        - is_lead_booker
                    - type: object
                      title: CreateOrderItemGuestNew
                      additionalProperties: false
                      properties:
                        name:
                          type: string
                        customer_id:
                          type: string
                      required:
                        - name
              practitioner_ids:
                type: array
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.practitioner_ids` instead.
                items:
                  type: string
              room_ids:
                type: array
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.room_ids` instead.
                items:
                  type: string
              equipment_ids:
                type: array
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.equipment_ids` instead.
                items:
                  type: string
              area_ids:
                type: array
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.area_ids` instead.
                items:
                  type: string
              skip_availability_checks:
                type: boolean
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.skip_availability_checks` instead.
              time:
                type: string
                format: date-time
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.time` instead.
              duration:
                type: integer
                minimum: 1
                deprecated: true
                description: This field is deprecated and only maintained for legacy reasons, use `item_configuration.duration` instead.
                example: 60
              item_configuration:
                type: object
                title: CreateOrderItemItemConfiguration
                additionalProperties: false
                properties:
                  time:
                    type: string
                    description: The date and time for this booking, in ISO 8601 format.
                    example: '2024-12-31T19:30:00+00:00'
                  date:
                    type: string
                    format: date
                    deprecated: true
                    description: This field is deprecated and only maintained for legacy reasons, pass a full datetime in the `item_configuration.time` field instead.
                  practitioner_ids:
                    type: array
                    items:
                      type: string
                    description: A list of practitioner IDs for appointment bookings.
                  practitioner_gender:
                    type: string
                    description: The requested gender for practitioner bookings, if applicable.
                    enum:
                      - male
                      - female
                  customer_requested_practitioner:
                    type: boolean
                    description: Whether the customer requested a specific practitioner, without specifying who. This is used for commission calculations, reporting, and analytics purposes, and does not affect availability or booking logic.
                  room_id:
                    type: string
                    description: The room ID for appointment bookings.
                  equipment_ids:
                    type: array
                    items:
                      type: string
                    description: A list of required equipment IDs for appointment bookings.
                  area_ids:
                    type: array
                    items:
                      type: string
                    description: A list of required area IDs for area bookings.
                  skip_availability_checks:
                    type: boolean
                    description: Whether to add this item without checking availability.
                  session_id:
                    type: string
                    description: The session ID for session bookings.
                  duration:
                    type: integer
                    minimum: 1
                    description: The duration in minutes for area bookings.
                  time_from:
                    type: string
                    description: The start time for appointment enquiries.
                    example: '2024-12-31T19:30:00+00:00'
                  time_to:
                    type: string
                    description: The end time for appointment enquiries.
                    example: '2024-12-31T20:30:00+00:00'
                  special_requests:
                    type: string
                    description: Any special requests for hotel room reservations.
                  check_in_date:
                    type: string
                    format: date
                    description: The check-in date for hotel room reservations.
                  check_out_date:
                    type: string
                    format: date
                    description: The check-out date for hotel room reservations.
                  room_guests:
                    type: array
                    description: A list of guests for hotel room reservations.
                    items:
                      type: object
                      title: CreateOrderItemRoomGuest
                      additionalProperties: false
                      properties:
                        quantity:
                          type: integer
                          minimum: 1
                  membership_type_id:
                    type: string
                    description: The membership type ID for memberships.
                  membership_rate_id:
                    type: string
                    description: The membership rate ID for memberships.
                  token:
                    type: string
                    description: The token for memberships.
                  source:
                    type: string
                    description: The source for memberships.
                  start_date:
                    type: string
                    format: date-time
                    description: The start date for memberships.
                  end_date:
                    type: string
                    format: date-time
                    description: The end date for memberships.
                  recipient_name:
                    type: string
                    description: The name of the voucher recipient.
                  amount:
                    type: number
                    description: The amount for the voucher.
                  recipient_email:
                    type: string
                    format: email
                    description: The email of the voucher recipient.
                  predetermined_code:
                    type: string
                    description: A predetermined code for the voucher.
                  delivery_date:
                    type: string
                    format: date
                    description: The delivery date for the voucher.
                  delivery_method_type:
                    type: string
                    enum:
                      - email
                      - physical
                    description: The delivery method type for the voucher.
                  address_line_1:
                    type: string
                    description: The first line of the address for physical voucher delivery.
                  address_line_2:
                    type: string
                    description: The second line of the address for physical voucher delivery.
                  country:
                    type: string
                    description: The country for physical voucher delivery.
                  county:
                    type: string
                    description: The county for physical voucher delivery.
                  town:
                    type: string
                    description: The town for physical voucher delivery.
                  postcode:
                    type: string
                    description: The postcode for physical voucher delivery.
                  delivery_option_id:
                    type: string
                    description: The delivery option ID for physical voucher delivery.
                  delivery_cost:
                    type: number
                    description: The delivery cost for physical voucher delivery.
                  customer_id:
                    type: string
                    description: The customer ID associated with the voucher.
                  custom_message:
                    type: string
                    maxLength: 500
                    description: A custom message to include with the voucher.
            required:
              - offering_type
              - offering_id
    UpdateOrderItem:
      description: |
        Fields to apply to the existing order item. All fields are
        optional; only the values you include in the payload are changed.
        The shape of the payload depends on the item's `item_type`.
      content:
        application/json:
          schema:
            title: UpdateOrderItem
            type: object
            additionalProperties: false
            properties:
              date:
                type: string
                format: date
                description: |
                  The date the booking should be moved to, formatted as
                  `YYYY-MM-DD`. Applicable to bookings (appointments,
                  area bookings, sessions, table reservations) and to
                  packages.
                example: '2025-03-14'
              time:
                type: string
                description: |
                  The local time the booking should start at, formatted
                  as `HH:MM`. Pass `null` to clear the time for items
                  whose booking is time-agnostic. Applicable to bookings
                  and packages.
                nullable: true
                example: '14:30'
              duration:
                type: integer
                minimum: 1
                description: |
                  The new duration of the booking in minutes. Applicable
                  to area bookings (and to appointments if the offering
                  allows variable durations).
                example: 60
              quantity:
                type: integer
                minimum: 1
                description: |
                  The number of units of this item to include in the
                  order. Most commonly used for retail products and
                  vouchers; bookings are typically always `1`.
                example: 2
              room_id:
                type: string
                nullable: true
                description: |
                  Override the room the booking is held in. Pass `null`
                  to clear an existing assignment and let the availability
                  engine pick one on confirmation. Use
                  `item_configuration.room_id` for new integrations; this
                  top-level field is retained for backwards compatibility.
                example: 5f1234567890abcdef123456
              practitioner_ids:
                type: array
                nullable: true
                description: |
                  The IDs of practitioners that should be assigned to
                  this booking. Use `item_configuration.practitioner_ids`
                  for new integrations; this top-level field is retained
                  for backwards compatibility.
                items:
                  type: string
              area_ids:
                type: array
                nullable: true
                description: |
                  The IDs of areas that should be reserved for this
                  booking. Required for area bookings, ignored for
                  other item types. Use `item_configuration.area_ids`
                  for new integrations; this top-level field is retained
                  for backwards compatibility.
                items:
                  type: string
              equipment_ids:
                type: array
                nullable: true
                description: |
                  The IDs of equipment items that should be held for this
                  booking. Use `item_configuration.equipment_ids` for new
                  integrations; this top-level field is retained for
                  backwards compatibility.
                items:
                  type: string
              discount_amount:
                type: integer
                minimum: 0
                nullable: true
                description: |
                  A manual discount amount in minor units (e.g. pence,
                  cents) to apply to this item. Only honoured when the
                  authenticated user has the `discounts:apply_manual`
                  permission on the order.
                example: 500
              offering_type:
                $ref: '#/components/schemas/OfferingType'
              offering_id:
                type: string
                description: |
                  The identifier of the offering to swap this item to.
                  Combined with `offering_type` to disambiguate which
                  collection the ID belongs to. Most commonly used to
                  switch an appointment to a different appointment type
                  or upgrade a session.
                example: 5f1234567890abcdef123456
              package_items:
                type: array
                description: |
                  The full list of choices for a package item. Pass the
                  complete new set on every update — items omitted from
                  this array are removed from the package.
                items:
                  type: object
                  title: UpdateOrderItemPackageItem
                  additionalProperties: false
                  properties:
                    id:
                      type: string
                      description: The ID of the existing package item being modified, when present.
                    choice_id:
                      type: string
                      description: The ID of the package choice this entry fulfils.
                    option_id:
                      type: string
                      description: The ID of the option within the choice.
                    guest_ids:
                      type: array
                      description: Guests to associate with the package item.
                      items:
                        type: string
                    item_configuration:
                      type: object
                      title: UpdateOrderItemPackageItemConfiguration
                      description: Item configuration overrides for the package item.
                      additionalProperties: true
              item_configuration:
                type: object
                title: UpdateOrderItemItemConfiguration
                description: |
                  The new configuration for the item. This is the
                  preferred place to set time, duration, resources and
                  other item-type specific fields. The accepted keys
                  mirror those documented for `createOrderItem`'s
                  `item_configuration`.
                additionalProperties: true
                properties:
                  time:
                    type: string
                    description: The date and time for this booking, in ISO 8601 format.
                    example: '2025-03-14T14:30:00+00:00'
                  practitioner_ids:
                    type: array
                    items:
                      type: string
                  room_id:
                    type: string
                    nullable: true
                  area_ids:
                    type: array
                    items:
                      type: string
                  equipment_ids:
                    type: array
                    items:
                      type: string
                  duration:
                    type: integer
                    minimum: 1
                  session_id:
                    type: string
                  skip_availability_checks:
                    type: boolean
              guest_ids:
                type: array
                nullable: true
                description: The full list of guest IDs that should be associated with this item.
                items:
                  type: string
              sold_by:
                type: object
                title: UpdateOrderItemSoldBy
                description: |
                  The staff member who should receive commission credit
                  for this item. Pass `null` to clear the existing sold
                  by attribution.
                nullable: true
                additionalProperties: false
                properties:
                  id:
                    type: string
                    description: The ID of the entity selling the offering.
                  type:
                    type: string
                    description: The type of the entity selling the offering (e.g. `user`).
                required:
                  - id
                  - type
              skip_availability_checks:
                type: boolean
                description: |
                  When true, bypasses availability rules during the
                  update. Requires the `reservations:override_rules`
                  permission. Useful for back-office corrections where
                  an item must be moved into a slot that would otherwise
                  be unavailable.
    ApplyDiscountToOrderItem:
      description: Apply a discount to an order item
      content:
        application/json:
          schema:
            title: ApplyDiscountToOrderItem
            type: object
            additionalProperties: false
            properties:
              discount_type_code:
                type: string
                description: The code for the discount type. If the code exists, the discount will be applied.
                example: SUMMER23
              applicable_for:
                type: string
                description: Where this discount type is able to be applied.
                example: app_and_booking_engine
                enum:
                  - app_only
                  - app_and_booking_engine
              discount_amount:
                type: integer
                description: |
                  The value of the discount to be applied when a discount type is used.
                  This can be used as a monetary or percentage value for an in-app discount type and is set to percentage for a promo code.
                example: 15
              amount_type:
                type: string
                description: |
                  The type of discount. For a promo code, this will always be a percentage.
                example: percentage
                enum:
                  - monetary
                  - percentage
            required:
              - discount_type_code
              - discount_amount
    UpdateItemSoldBy:
      description: Includes details of the staff member responsible for selling an order item.
      content:
        application/json:
          schema:
            title: UpdateItemSoldBy
            type: object
            additionalProperties: false
            properties:
              sold_by:
                type: string
                description: The code for the discount type. If the code exists, the discount will be applied.
                format: mongo-id
            required:
              - sold_by
    UpdateOrderLabels:
      description: Update the labels on an order.
      content:
        application/json:
          schema:
            title: UpdateOrderLabels
            type: object
            additionalProperties: false
            properties:
              labels:
                type: array
                items:
                  $ref: '#/components/schemas/UpdateOrderLabel'
            required:
              - labels
    CreateOrderNote:
      description: The body required to add a note to an order.
      content:
        application/json:
          schema:
            title: CreateOrderNote
            type: object
            additionalProperties: false
            required:
              - content
            properties:
              content:
                type: string
                description: |
                  The contents of the note. HTML is not permitted — submit plain text only.
                  Use notes to capture operational context for the order (for example,
                  special requests from the guest, or an internal note for the front desk).
                example: Guest requested a double treatment room and prefers a female therapist.
    UpdateOrderNote:
      description: The body required to update an existing order note.
      content:
        application/json:
          schema:
            title: UpdateOrderNote
            type: object
            additionalProperties: false
            required:
              - content
            properties:
              content:
                type: string
                description: |
                  The new contents of the note. HTML is not permitted — submit plain text only.
                example: Guest no longer requires a double treatment room.
    UpdateOrderServiceCharge:
      description: Update the service charge on an order.
      content:
        application/json:
          schema:
            title: UpdateOrderServiceCharge
            type: object
            additionalProperties: false
            properties:
              amount:
                type: integer
                description: The amount of service charge, in minor units. Required if item_amounts isn't specified.
                example: 1050
              item_amounts:
                type: array
                items:
                  $ref: '#/components/schemas/ItemServiceChargeAmount'
    UpdateOrderTip:
      description: Update the tip on an order.
      content:
        application/json:
          schema:
            title: UpdateOrderTip
            type: object
            additionalProperties: false
            properties:
              amount:
                type: integer
                description: The amount of tip, in minor units.
                example: 1050
              basket_item_ids:
                type: array
                description: An array of basket item IDs to which the tip should be applied. If not provided, the tip will be applied to all applicable items in the order.
                items:
                  type: string
                  format: object-id
                example:
                  - 60f7c2ab4f1a256e1c8b4567
                  - 60f7c2ab4f1a256e1c8b4568
                nullable: true
            required:
              - amount
    SendSmsMessage:
      description: Send an SMS message
      content:
        application/json:
          schema:
            title: SendSmsMessage
            type: object
            additionalProperties: false
            properties:
              message_type:
                type: string
                description: The type of message the SMS message is.
                enum:
                  - basket_confirmed
                  - basket_cancelled_with_charge
                  - basket_cancelled_without_charge
                  - basket_reminder
                  - basket_follow_up
                  - pay_by_link_request
              params:
                $ref: '#/components/schemas/SmsMessageParams'
            required:
              - message_type
    PreviewSmsMessage:
      description: Create a preview of an SMS message for an order
      content:
        application/json:
          schema:
            title: PreviewSmsMessage
            type: object
            additionalProperties: false
            properties:
              message_type:
                type: string
                description: The type of the SMS message.
                enum:
                  - basket_confirmed
                  - basket_cancelled_with_charge
                  - basket_cancelled_without_charge
                  - basket_reminder
                  - basket_follow_up
                  - pay_by_link_request
              params:
                $ref: '#/components/schemas/SmsMessageParams'
            required:
              - message_type
    SuppressSmsMessage:
      description: Suppress an SMS message
      content:
        application/json:
          schema:
            title: SuppressSmsMessage
            type: object
            additionalProperties: false
            properties:
              message_type:
                type: string
                description: The type of message the SMS message is.
                enum:
                  - basket_reminder
                  - basket_follow_up
              suppress:
                type: boolean
                description: Whether the SMS message should be suppressed.
                example: true
            required:
              - message_type
              - suppress
    AddCustomerToOrder:
      description: Add a customer to an order.
      content:
        application/json:
          schema:
            title: AddCustomerToOrder
            type: object
            additionalProperties: false
            properties:
              id:
                type: string
                description: |
                  Identifier of the customer to attach as the lead booker
                  on this order. Where `source` is `trybe` this is the
                  Trybe customer UUID; for third-party sources it's the
                  external customer reference from the PMS or CRM.
                example: abc123
              source:
                type: string
                description: The source of the customer addition
                example: trybe
            required:
              - id
    ApplyCustomerCreditToOrder:
      description: |
        The body required to apply a customer credit to an order. The credit must
        belong to a customer that's eligible to redeem it against this order — if
        not, a `400 Bad Request` is returned describing why the credit can't be
        used.
      content:
        application/json:
          schema:
            title: ApplyCustomerCreditToOrder
            type: object
            additionalProperties: false
            required:
              - id
            properties:
              id:
                type: string
                description: |
                  Identifier of the `CustomerCredit` to apply to this order.
                  Customer credits are managed under the Customers API and
                  must belong to a customer linked (directly or via a guest)
                  to this order.
                example: 5ed2b95f72823c4f98419f19
    CreateCategory:
      description: To create a category, you pass a `Category` object.
      required: true
      content:
        application/json:
          schema:
            title: CreateCategory
            allOf:
              - $ref: '#/components/schemas/requestBody-content-application~1json-schema'
              - type: object
                required:
                  - name
    UpdateCategoryOrder:
      description: Pass an object containing an array of ordered category IDs.
      required: true
      content:
        application/json:
          schema:
            title: UpdateCategoryOrder
            type: object
            additionalProperties: false
            properties:
              category_ids:
                type: array
                description: The category IDs in their desired display order.
                items:
                  type: string
                  format: uuid
            required:
              - category_ids
    UpdateCategoryLocaleStrings:
      description: Update locale strings for a Category
      required: true
      content:
        application/json:
          schema:
            title: UpdateCategoryLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this category in the given locale.
                example: Massages
    CreateCustomPaymentType:
      description: To create a custom payment type, you pass a `CustomPaymentType` object.
      required: true
      content:
        application/json:
          schema:
            title: CreateCustomPaymentType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name shown to staff when accepting payment.
                  1-120 characters; required.
                example: Hotel Folio
              kind:
                type: string
                enum:
                  - pms_prepaid
                  - voucher
                  - prepayment
                nullable: true
                description: |
                  Optional classification used to drive special handling.
                  See the `kind` field on `CustomPaymentType` for the full
                  meaning of each value.
                example: pms_prepaid
              fiscalisation_type:
                type: string
                enum:
                  - unknown
                  - cash
                  - debit_card
                  - credit_card
                  - voucher
                  - online
                nullable: true
                description: |
                  Optional mapping used when posting to fiscalisation
                  integrations that require a tender-type code.
                example: cash
            required:
              - name
    UpdateCustomPaymentType:
      description: Updates the specified `CustomPaymentType` object by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
      required: true
      content:
        application/json:
          schema:
            title: UpdateCustomPaymentType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Updated display name. When omitted the existing name is
                  preserved.
                example: Hotel Folio
              kind:
                type: string
                enum:
                  - pms_prepaid
                  - voucher
                  - prepayment
                nullable: true
                description: |
                  Updated classification. Pass `null` to clear back to the
                  generic-tender default.
                example: pms_prepaid
              fiscalisation_type:
                type: string
                enum:
                  - unknown
                  - cash
                  - debit_card
                  - credit_card
                  - voucher
                  - online
                nullable: true
                description: Updated fiscalisation mapping.
                example: cash
    CreateSessionType:
      description: |
        Body for creating a new `SessionType`. `name` is the only required
        field; everything else has a sensible default. `SessionType`s are
        typically paired with `SessionRecurrenceGroup`s after creation to
        drive a recurring schedule.
      required: true
      content:
        application/json:
          schema:
            title: CreateSessionType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the session type, shown to customers in
                  the shopfront and to staff in the admin UI. Plain text
                  only — HTML tags are rejected.
                example: Vinyasa Yoga
              description:
                type: string
                description: |
                  Long-form description shown to customers when they're
                  selecting the session type. Markdown is rendered.
                example: |
                  A flowing, breath-linked sequence of postures suitable
                  for most levels.
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map this session type to an
                  external POS/PMS catalog. Free-form; uniqueness not
                  enforced server-side.
                example: YOGA-VINYASA
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this offering.
                example: ext-yoga-vinyasa
              currency:
                $ref: '#/components/schemas/properties_currency'
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this session type, in the
                  smallest currency unit (e.g. pence). Optional at create
                  time — session types can be created without a standard
                  price and have one configured later.
                example: 5000
              organisation_id:
                type: string
                format: uuid
                description: |
                  Optional organisation to attribute this offering to.
                  Defaults to the caller's primary organisation.
              duration:
                type: integer
                minimum: 1
                description: |
                  Length of each session occurrence in minutes. Sessions
                  have a single duration (unlike appointment types which
                  can support several).
                example: 60
              max_baskets_per_session:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum number of baskets (= customer parties) that can
                  book a single session occurrence. Beyond this, the
                  session is full. Null = unlimited.
                example: 12
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
                description: Category IDs for shopfront grouping.
              offered_online:
                type: boolean
                description: |
                  When true, the session type is bookable via the public
                  shopfront. When false, it's admin-only.
              private:
                type: boolean
                description: When true, only customers with the direct link can book this session type.
              visibility:
                type: string
                enum:
                  - public
                  - hidden
                  - members_only
                description: |
                  Visibility override. `public` = everyone; `hidden` = out
                  of search/browse (still bookable by direct link);
                  `members_only` = restricted to permitted membership-type
                  holders.
              customers_only:
                type: boolean
                description: When true, only registered customers can book.
              members_only:
                type: boolean
                description: When true, only members of permitted membership types can book.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: |
                  Membership type IDs whose members can book when
                  `members_only=true`. Out-of-brand membership types are
                  filtered out.
              membership_booking_windows_enabled:
                type: boolean
                description: |
                  When true, members get extended advance-booking windows
                  per `membership_booking_windows`.
              membership_booking_windows:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
                description: Per-membership-type advance-window overrides.
              max_bookings_per_member:
                type: integer
                minimum: 1
                description: |
                  Cap on how many concurrent bookings a single member can
                  hold for this session type. Helps prevent block-booking
                  of limited-capacity offerings.
                example: 2
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum guests per basket when booking this session type.
                  Null = unlimited (subject to `max_baskets_per_session`).
                example: 4
              waitlist_enabled:
                type: boolean
                description: |
                  When true, customers can join a waitlist once the session
                  is full; they're notified if a spot opens up.
              max_waitlist_size:
                type: integer
                nullable: true
                description: |
                  Maximum number of customers allowed on the waitlist.
                  Null = unlimited.
                example: 10
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration limiting how far in advance customers
                  can book. e.g. `P30D` = 30 days, `P1Y` = 1 year.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration of minimum notice before booking. e.g.
                  `PT2H` = at least 2 hours.
                example: PT2H
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Revenue centre to post session bookings to. Must be valid
                  for the caller's site.
                example: spa
              upsell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
                description: Upsell candidates at booking confirmation.
              cross_sell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
                description: Cross-sell candidates during the booking flow.
              related_retail_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
                description: Retail product candidates to surface alongside this session type.
              meta:
                type: object
                title: CreateSessionTypeMeta
                additionalProperties: false
                description: SEO metadata for the shopfront page.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                    description: Page title in browser tabs and search results.
                    example: Vinyasa Yoga at Riverside Spa
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
                    description: Meta description shown in search-engine snippets.
                    example: 60-minute flowing yoga sequence, suitable for most levels.
            required:
              - name
    UpdateSessionType:
      description: |
        Partial update for a `SessionType`. Every field is optional; only
        fields you send are written. Omitted fields retain their current
        values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateSessionType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name. Plain text only.
                example: Vinyasa Yoga
              description:
                type: string
                nullable: true
                description: Long-form description. Markdown rendered.
                example: A flowing breath-linked yoga sequence suitable for most levels.
              product_code:
                type: string
                nullable: true
                description: Optional product code for POS/PMS mapping.
                example: YOGA-VINYASA
              external_id:
                type: string
                nullable: true
                description: External identifier for integrations.
                example: ext-yoga-vinyasa
              currency:
                $ref: '#/components/schemas/properties_currency'
              yield_management:
                $ref: '#/components/schemas/YieldManagement'
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this session type, in the
                  smallest currency unit (e.g. pence). Pass `null` to
                  clear a previously-set standard price.
                example: 5000
              duration:
                type: integer
                minimum: 1
                description: Session length in minutes.
                example: 60
              max_baskets_per_session:
                type: integer
                nullable: true
                minimum: 1
                description: Maximum baskets per session occurrence.
                example: 12
              category_ids:
                type: array
                items:
                  type: string
                  format: object-id
              offered_online:
                type: boolean
                description: Whether bookable via the public shopfront.
              private:
                type: boolean
                description: Direct-link-only booking.
              visibility:
                type: string
                enum:
                  - public
                  - hidden
                  - members_only
                description: |
                  Visibility override that determines who sees this session
                  type on the shopfront. `public` = everyone; `hidden` =
                  out of search/browse (still bookable by direct link);
                  `members_only` = restricted to permitted membership-type
                  holders.
              customers_only:
                type: boolean
                description: Restrict to registered customers.
              members_only:
                type: boolean
                description: Restrict to permitted membership-type members.
              permitted_membership_type_ids:
                type: array
                nullable: true
                items:
                  type: string
                  format: uuid
                description: Membership-type IDs whose members may book.
              membership_booking_windows_enabled:
                type: boolean
                description: Whether to honour per-membership advance windows.
              membership_booking_windows:
                type: array
                items:
                  $ref: '#/components/schemas/MembershipBookingWindow'
              max_bookings_per_member:
                type: integer
                minimum: 1
                description: Concurrent-booking cap per member.
                example: 2
              max_guests:
                type: integer
                nullable: true
                minimum: 1
                description: |
                  Maximum guests per basket for this session type. Subject
                  to `max_baskets_per_session` and the overall session
                  capacity. Null = no per-basket cap.
                example: 4
              waitlist_enabled:
                type: boolean
                description: Allow customers to join a waitlist when full.
              max_waitlist_size:
                type: integer
                nullable: true
                description: Maximum number of customers allowed on the waitlist. Null = unlimited.
                example: 10
              max_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 max-advance booking duration.
                example: P30D
              min_advance_bookings_interval:
                type: string
                nullable: true
                description: ISO 8601 min-advance booking duration.
                example: PT2H
              revenue_centre:
                type: string
                nullable: true
                description: Revenue centre for session bookings.
                example: spa
              upsell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` for the cover image.
                example: 5f1234567890abcdef123456
              meta:
                type: object
                title: UpdateSessionTypeMeta
                additionalProperties: false
                description: |
                  SEO metadata for the session type's public shopfront
                  page — page title and meta description used in browser
                  tabs and search engine snippets.
                properties:
                  title:
                    type: string
                    nullable: true
                    maxLength: 120
                  description:
                    type: string
                    nullable: true
                    maxLength: 140
    CreateSessionTypePriceRule:
      description: |
        Body for creating a new `PriceRule` on a `SessionType`. Only `price`
        is strictly required; all other fields are filters that restrict
        when the rule applies. Note: session price rules don't have a
        `duration` filter (sessions have a single duration set on the
        `SessionType` itself).
      required: true
      content:
        application/json:
          schema:
            title: CreateSessionTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: |
                  Price in the smallest currency unit (e.g. pence, cents).
                  `4800` means £48.00 in a GBP-denominated site.
                example: 4800
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive). Defaults to today in the site's timezone if omitted.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive). When omitted, the rule has no end date.
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Start of the time-of-day window in 24-hour `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: End of the time-of-day window in 24-hour `HH:MM`. Must be later than `time_from`.
                example: '18:00'
              weekdays:
                type: array
                nullable: true
                description: Days of the week the rule applies on. Empty/null means every day.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - saturday
                  - sunday
            required:
              - price
    UpdateSessionTypePriceRule:
      description: |
        Body for updating an existing `PriceRule`. Every field is optional;
        omitted fields keep their current values.
      required: true
      content:
        application/json:
          schema:
            title: UpdateSessionTypePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: Price in the smallest currency unit.
                example: 4800
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies.
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Start of the time-of-day window in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: End of the time-of-day window in `HH:MM`.
                example: '18:00'
              weekdays:
                type: array
                nullable: true
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
    UpdateSessionTypeLocaleStrings:
      description: Update locale strings for a SessionType
      required: true
      content:
        application/json:
          schema:
            title: UpdateSessionTypeLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this session type in the given locale.
                example: Morning Yoga
              description:
                type: string
                nullable: true
                description: The localised description for this session type in the given locale.
                example: A morning yoga session suitable for all levels.
              meta_title:
                type: string
                nullable: true
                description: The localised meta title for this session type in the given locale.
                example: Morning Yoga Class | Book a Spot
              meta_description:
                type: string
                nullable: true
                description: The localised meta description for this session type in the given locale.
                example: Start your day with our morning yoga session, open to all levels.
    CreateShopSiteOpeningHoursOverride:
      required: true
      content:
        application/json:
          schema:
            title: CreateShopSiteOpeningHoursOverride
            type: object
            additionalProperties: false
            required:
              - date_from
              - date_to
            properties:
              date_from:
                $ref: '#/components/schemas/date_from'
              date_to:
                $ref: '#/components/schemas/date_to'
              is_available:
                $ref: '#/components/schemas/is_available'
              time_from:
                $ref: '#/components/schemas/time_from'
              time_to:
                $ref: '#/components/schemas/time_to'
    UpdateShopSiteOpeningHoursOverride:
      required: true
      content:
        application/json:
          schema:
            title: UpdateShopSiteOpeningHoursOverride
            type: object
            additionalProperties: false
            properties:
              date_from:
                $ref: '#/components/schemas/date_from'
              date_to:
                $ref: '#/components/schemas/date_to'
              is_available:
                $ref: '#/components/schemas/is_available'
              time_from:
                $ref: '#/components/schemas/time_from'
              time_to:
                $ref: '#/components/schemas/time_to'
    UpdateSmsNotificationSettings:
      description: Update SMS Notification Settings
      content:
        application/json:
          schema:
            type: object
            title: UpdateSmsNotificationSettings
            additionalProperties: false
            properties:
              confirmation_sms_enabled:
                type: boolean
                description: |
                  Whether the order confirmation SMS is enabled.
                example: false
              automated_confirmation_sms_enabled:
                type: boolean
                description: |
                  Whether the order confirmation SMS has automation turned off or not.
                example: false
              cancellation_sms_enabled:
                type: boolean
                description: |
                  Whether the order cancellation SMS is enabled.
                example: false
              pay_by_link_sms_enabled:
                type: boolean
                description: |
                  Whether the pay by link request SMS is enabled.
                example: false
              billing_details_request_sms_enabled:
                type: boolean
                description: |
                  Whether the billing details request SMS for memberships is enabled.
                example: false
              waitlist_confirmation_sms_enabled:
                type: boolean
                description: |
                  Whether the waitlist update SMS is enabled.
                example: false
              reminder_sms_enabled:
                type: boolean
                description: |
                  Whether the reminder SMS is enabled.
                example: false
              automated_reminder_sms_enabled:
                type: boolean
                description: |
                  Whether the order reminder SMS has automation turned off or not.
                example: false
              reminder_sms_time:
                type: string
                format: time
                description: |
                  The time of day the reminder SMS will be sent for automated messages.
              reminder_sms_days_ahead:
                type: integer
                description: |
                  The number of days ahead of the booking the reminder SMS will be sent for automated messages.
                example: 3
              follow_up_sms_enabled:
                type: boolean
                description: |
                  Whether the follow up SMS is enabled.
                example: false
              automated_follow_up_sms_enabled:
                type: boolean
                description: |
                  Whether the order follow up SMS has automation turned off or not.
                example: false
              follow_up_sms_time:
                type: string
                format: time
                description: |
                  The time of day the follow up SMS will be sent for automated messages.
              follow_up_sms_days_after:
                type: integer
                description: |
                  The number of days after the booking the follow up SMS will be sent for automated messages.
                example: 3
              sid:
                type: string
                description: |
                  The sender identifier registered with the SMS gateway. For Twilio this is the alphanumeric sender ID or Messaging Service SID; recipients see it as the "from" name on the text. Country restrictions on alphanumeric sender IDs apply.
                example: SENDERSPA
              provider:
                type: string
                description: |
                  Which SMS gateway sends outbound texts for this site. Only `twilio` is supported today; new sites should leave this at the default and configure Twilio credentials separately in the integrations section.
                example: twilio
              from_number:
                type: string
                description: |
                  The phone number the SMS will be sent from.
                example: '+1234567890'
              confirmation_sms_offerings:
                type: array
                description: |
                  The offerings that automated confirmation texts are sent for. If empty, confirmation texts are sent for all offerings.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              reminder_sms_offerings:
                type: array
                description: |
                  The offerings that automated reminder texts are sent for. If empty, reminder texts are sent for all offerings.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              follow_up_sms_offerings:
                type: array
                description: |
                  The offerings that automated follow up texts are sent for. If empty, follow up texts are sent for all offerings.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
    UpdateSupportedCommsLocales:
      content:
        application/json:
          schema:
            title: UpdateSupportedCommsLocales
            type: object
            additionalProperties: false
            properties:
              locales:
                type: array
                items:
                  type: string
                description: |
                  A list of locales that are supported by the site.

                  This should be a string of locale codes that are supported by the platform.
                example:
                  - en
                  - fr
                  - de
    UpdateSiteLegalLocaleStrings:
      description: Update legal locale strings for a Site
      required: true
      content:
        application/json:
          schema:
            title: UpdateSiteLegalLocaleStrings
            type: object
            additionalProperties: false
            properties:
              terms:
                type: string
                nullable: true
                description: The localised terms and conditions for the site in the given locale.
                example: <p>By booking with us, you agree to our terms and conditions.</p>
              privacy_policy:
                type: string
                nullable: true
                description: The localised privacy policy for the site in the given locale.
                example: <p>We take your privacy seriously.</p>
    UpdateSiteFeatures:
      description: Update the features of a Site
      content:
        application/json:
          schema:
            type: object
            title: UpdateSiteFeatures
            additionalProperties: false
            properties:
              support_wearable_payments:
                type: boolean
                description: Whether the site supports wearable payments
              support_terminal_initiated_payments:
                type: boolean
                description: Whether the site supports terminal initiated payments
              terminal_payment_retail_product_id:
                type: string
                format: object-id
                description: |
                  Identifier of the retail product used to back ad-hoc
                  terminal-initiated payments (e.g. open-amount tap-to-pay
                  charges). The product's revenue centre is what the
                  resulting sale will post to. Pass `null` to disable
                  terminal-initiated payments.
                nullable: true
    OrderedOfferings:
      description: List of ordered offerings
      content:
        application/json:
          schema:
            type: object
            title: OrderedOfferings
            additionalProperties: false
            properties:
              offering_ids:
                type: array
                items:
                  type: string
                  description: The IDs of ordered offerings
            required:
              - offering_ids
    UpdateSsoConfig:
      description: Update the `SsoConfig` for a site
      content:
        application/json:
          schema:
            type: object
            title: UpdateSsoConfig
            additionalProperties: false
            properties:
              id:
                type: string
                format: uuid
                description: |
                  Identifier of the SSO configuration to update, returned
                  by the SSO config read endpoint. Must match the
                  configuration currently attached to the site in the URL.
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site that owns this SSO configuration.
                  Must match the `siteId` in the request URL; provided
                  redundantly to make the body self-describing for audit
                  logs.
              type:
                type: string
                description: The type of SSO configuration.
                example: customer_sso
              enabled:
                type: boolean
                description: Whether the SSO configuration is enabled.
                example: true
              authorize_url:
                type: string
                description: The URL to redirect to for authorization.
                example: https://api.trybe.test/authorize
              credentials:
                type: object
                title: SsoCredentials
                description: |
                  The credentials required for the SSO configuration.
                additionalProperties: false
                properties:
                  client_id:
                    type: string
                    description: The client ID for the SSO configuration.
                    example: '1234'
                  client_secret:
                    type: string
                    description: The client secret for the SSO configuration.
                    example: s3cr3tK3y123!@#
                  additional_authorize_query_params:
                    type: array
                    description: Additional query parameters to include in the authorization request.
                    items:
                      type: object
                      title: SsoAdditionalAuthorizeQueryParams
                      additionalProperties: false
                      properties:
                        key:
                          type: string
                          description: The key of the query parameter.
                        value:
                          type: string
                          description: The value of the query parameter.
                  additional_token_query_params:
                    type: array
                    description: Additional query parameters to include in the token request.
                    items:
                      type: object
                      title: SsoAdditionalTokenQueryParams
                      additionalProperties: false
                      properties:
                        key:
                          type: string
                          description: The key of the query parameter.
                        value:
                          type: string
                          description: The value of the query parameter.
              token_url:
                type: string
                description: The URL to request an access token.
                example: https://api.trybe.test/token
              user_info_url:
                type: string
                description: The URL to request user information.
                example: https://api.trybe.test/userinfo
              scopes:
                type: array
                description: The scopes to request during authorization.
                items:
                  type: string
                  example: openid
              include_existing_url_params:
                type: boolean
                description: Whether to include existing URL parameters in the authorization request.
                example: false
              token_request_style:
                type: string
                enum:
                  - form_params
                  - json
                description: The style of the token request.
                example: form_params
              user_mappings:
                type: array
                description: Mappings from user attributes to SSO token fields.
                items:
                  type: object
                  title: SsoUserMapping
                  additionalProperties: false
                  properties:
                    key:
                      type: string
                      description: The user attribute key.
                      example: full_name
                    fields:
                      type: array
                      description: The fields from the SSO token to map to the user attribute.
                      items:
                        type: string
                        example: email
    CreateMessageFragment:
      description: Create a message fragment.
      required: true
      content:
        application/json:
          schema:
            title: CreateMessageFragment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the fragment, shown in the admin UI
                  when authoring email templates. Not visible to customers.
                example: Spa - arrival instructions
              message_type:
                type: string
                description: |
                  Which transactional email this fragment is included in.
                  Required at creation; cannot be inferred from any other
                  field.
                enum:
                  - basket_cancelled
                  - basket_confirmed
                  - basket_follow_up
                  - basket_item_cancelled
                  - basket_reminder
                  - order_summary
                  - pay_by_link_request
                  - appointment_enquiry_confirmed
                  - visit_prompt
                  - membership_welcome
                  - membership_cancelled
                  - voucher_recipient
                  - membership_enquiry_confirmed
                  - new_order
                  - new_enquiry
                example: basket_confirmed
              message:
                type: string
                nullable: true
                description: |
                  Body of the fragment. Accepts a restricted subset of HTML
                  tags (basic block and inline) which is sanitised on save.
                  Liquid-style placeholders are interpolated at send time.
                example: |
                  <p>Hi {{ customer.first_name }} - we're looking forward
                  to seeing you on {{ booking.starts_at|date }}.</p>
              priority:
                type: integer
                minimum: 1
                nullable: true
                description: |
                  Render order within a message. Fragments are concatenated
                  in ascending `priority` order. Omit to leave unordered.
                example: 10
              offerings:
                type: array
                description: |
                  Offerings the fragment applies to. Empty means the
                  fragment applies to every offering at the site.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  Optional list of `MembershipType` IDs. When set, the
                  fragment is only rendered for customers who hold an
                  active membership of one of these types.
                items:
                  type: string
                  format: mongo-id
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this fragment belongs to.
                  Fragments are scoped per site so each location can
                  author its own transactional email copy.
            required:
              - name
              - message_type
              - site_id
    UpdateMessageFragment:
      description: Update a message fragment.
      required: true
      content:
        application/json:
          schema:
            title: UpdateMessageFragment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the fragment, shown in the admin UI
                  when authoring email templates. Not visible to customers.
                example: Spa - arrival instructions
              message_type:
                type: string
                description: |
                  Which transactional email this fragment is included in.
                enum:
                  - basket_cancelled
                  - basket_confirmed
                  - basket_follow_up
                  - basket_item_cancelled
                  - basket_reminder
                  - order_summary
                  - pay_by_link_request
                  - appointment_enquiry_confirmed
                  - visit_prompt
                  - membership_welcome
                  - membership_cancelled
                  - voucher_recipient
                  - membership_enquiry_confirmed
                  - new_order
                  - new_enquiry
              message:
                type: string
                nullable: true
                description: |
                  Body of the fragment. Accepts a restricted subset of
                  HTML and is sanitised on save. Liquid-style
                  placeholders are interpolated at send time.
                example: |
                  <p>Hi {{ customer.first_name }} - we're looking forward
                  to seeing you soon.</p>
              priority:
                type: integer
                minimum: 1
                nullable: true
                description: |
                  Render order within a message. Fragments are concatenated
                  in ascending `priority` order.
                example: 10
              offerings:
                type: array
                description: |
                  Offerings the fragment applies to. Empty means the
                  fragment applies to every offering at the site.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  `MembershipType` IDs the fragment is restricted to.
                  Omit (or send an empty array) to clear the membership
                  filter; the field is reset when not present in the
                  request body.
                items:
                  type: string
                  format: mongo-id
            required:
              - name
    CopyMessageFragment:
      description: |
        Body for copying a `MessageFragment`. All fields are optional and
        override the corresponding field on the new copy; fields omitted
        are inherited from the source. The `name` is typically set so the
        copy is distinguishable from the source in the admin list.
      required: true
      content:
        application/json:
          schema:
            title: CopyMessageFragment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the new copy. Conventionally the
                  source's name suffixed with "(Copy)" or a variant tag.
                example: Spa - arrival instructions (Copy)
              message_type:
                type: string
                description: |
                  Override the `message_type` on the new copy. Defaults
                  to the source's value.
                enum:
                  - basket_cancelled
                  - basket_confirmed
                  - basket_follow_up
                  - basket_item_cancelled
                  - basket_reminder
                  - order_summary
                  - pay_by_link_request
                  - appointment_enquiry_confirmed
                  - visit_prompt
                  - membership_welcome
                  - membership_cancelled
                  - voucher_recipient
                  - membership_enquiry_confirmed
                  - new_order
                  - new_enquiry
              message:
                type: string
                nullable: true
                description: |
                  Body of the fragment. Defaults to the source's value.
                example: |
                  <p>Hi {{ customer.first_name }} - we're looking forward
                  to seeing you soon.</p>
              priority:
                type: integer
                minimum: 1
                nullable: true
                description: |
                  Render order within a message. Fragments are concatenated
                  in ascending `priority` order.
                example: 10
              offerings:
                type: array
                description: |
                  Offerings the fragment applies to. Empty means the
                  fragment applies to every offering at the site.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  `MembershipType` IDs the new copy is restricted to.
                items:
                  type: string
                  format: mongo-id
            required:
              - name
    AddMessageFragmentOffering:
      description: |
        Body for attaching an offering to a `MessageFragment`. The
        `offering` is identified by its type and ID; the server resolves
        the human-readable name and stores the full identifier on the
        fragment. Adding the same offering twice is a no-op.
      required: true
      content:
        application/json:
          schema:
            title: AddMessageFragmentOffering
            type: object
            additionalProperties: false
            properties:
              offering:
                allOf:
                  - $ref: '#/components/schemas/OfferingIdentifier'
                description: |
                  The offering to attach. Must reference an offering that
                  exists at the fragment's site. The `offering_name` may
                  be supplied for convenience but is re-resolved by the
                  server before being persisted.
            required:
              - offering
    UpdateMessageFragmentLocaleStrings:
      description: Update locale strings for a MessageFragment
      required: true
      content:
        application/json:
          schema:
            title: UpdateMessageFragmentLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this message fragment in the given locale.
                example: Spa - arrival instructions
              message:
                type: string
                nullable: true
                description: The localised message body for this message fragment in the given locale.
                example: <p>Welcome to our spa. Please arrive 15 minutes early to check in.</p>
    CreateSmsFragment:
      description: Create an SMS Message Fragment
      content:
        application/json:
          schema:
            title: CreateSmsFragment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the SMS fragment, shown in the admin
                  UI when authoring SMS templates. Not visible to customers.
                  1-120 characters.
                example: Order Confirmation
              message_type:
                type: string
                description: The type of message the SMS Fragment applies to.
                enum:
                  - basket_confirmed
                  - basket_cancelled_with_charge
                  - basket_cancelled_without_charge
                  - basket_reminder
                  - basket_follow_up
                  - pay_by_link_request
              message:
                type: string
                description: The contents of the SMS Fragment.
                example: |
                  Hi! Your order has been confirmed. We look forward to seeing you on Saturday 20th January at 12pm.
              priority:
                type: integer
                description: The priority of the SMS Fragment. Fragments will be added to messages in ascending order.
                example: 10
              offerings:
                type: array
                description: |
                  An array of offerings which the SMS Fragment applies to. If empty, the SMS Fragment applies to no offerings.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this SMS fragment is sent on behalf
                  of. Fragments are scoped per site so each location can
                  compose its own SMS copy and sender name.
              organisation_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation that owns the site. Used
                  for cross-site reporting and to enforce that the supplied
                  `site_id` belongs to this organisation.
            required:
              - name
              - message_type
              - site_id
              - organisation_id
    UpdateSmsFragment:
      description: Update an SMS Message Fragment
      content:
        application/json:
          schema:
            title: UpdateSmsFragment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the SMS fragment, shown in the admin
                  UI when authoring SMS templates. Not visible to customers.
                  1-120 characters.
                example: Order Confirmation
              message_type:
                type: string
                description: The type of message the SMS Fragment applies to.
                enum:
                  - basket_confirmed
                  - basket_cancelled_with_charge
                  - basket_cancelled_without_charge
                  - basket_reminder
                  - basket_follow_up
                  - pay_by_link_request
              message:
                type: string
                description: The contents of the SMS Fragment.
                example: |
                  Hi! Your order has been confirmed. We look forward to seeing you on Saturday 20th January at 12pm.
              priority:
                type: integer
                description: The priority of the SMS Fragment. Fragments will be added to messages in ascending order.
                example: 10
              offerings:
                type: array
                description: |
                  An array of offerings which the SMS Fragment applies to. If empty, the SMS Fragment applies to no offerings.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              site_id:
                type: string
                format: uuid
                description: |
                  Identifier of the site this SMS fragment is sent on behalf
                  of. Fragments are scoped per site so each location can
                  compose its own SMS copy and sender name.
              organisation_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation that owns the site. Used
                  for cross-site reporting and to enforce that the supplied
                  `site_id` belongs to this organisation.
    CopySmsFragment:
      description: |
        Body for copying an `SmsFragment`. All fields are optional and
        override the corresponding field on the new copy; fields omitted
        are inherited from the source. The `name` is typically set so the
        copy is distinguishable from the source in the admin list.
      required: true
      content:
        application/json:
          schema:
            title: CopySmsFragment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Internal label for the new copy. Conventionally the
                  source's name suffixed with "(Copy)" or a variant tag.
                example: Order Confirmation (Copy)
              message_type:
                type: string
                description: The type of message the SMS Fragment applies to. Defaults to the source's value.
                enum:
                  - basket_confirmed
                  - basket_cancelled_with_charge
                  - basket_cancelled_without_charge
                  - basket_reminder
                  - basket_follow_up
                  - pay_by_link_request
              message:
                type: string
                nullable: true
                description: Contents of the SMS Fragment.
                example: |
                  Hi! Your order has been confirmed. We look forward to
                  seeing you soon.
              priority:
                type: integer
                minimum: 1
                nullable: true
                description: |
                  Priority of the SMS Fragment. Fragments are concatenated
                  in ascending priority order to build the final message.
                example: 10
              offerings:
                type: array
                description: |
                  Offerings the SMS Fragment applies to. Empty/omitted means
                  the fragment applies to no specific offerings (use the
                  global fallback).
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
    CreateMembership:
      description: |
        The details of the membership to create. A `Membership` always requires a `Customer`, but
        for convenience, you can pass `customer_data` to create the customer inline and attach
        the membership to the newly created customer.

        Unless you're authorised to do so, you'll only be permitted to create a membership for a
        private `MembershipType` and/or a non-default `MembershipRate` when you provide a valid
        `MembershipSignupToken` ID for the type and rate in question.

        The status of newly created memberships is always 'reserved'. You'll need to make a request
        to the memberships/:membershipId/confirm endpoint to update the status - this should be done
        once the pro-rata or joining fee payment has been paid.
      content:
        application/json:
          schema:
            title: CreateMembership
            type: object
            additionalProperties: false
            description: |
              To attach a new membership to an existing customer, pass the customer ID in on the `customer_id`
              field. Otherwise, you must create the customer inline with the `customer_data` field.
            properties:
              customer_id:
                type: string
                description: |
                  The `Customer` the new membership should be attached to.
                  Mutually exclusive with `customer_data`: pass exactly one
                  of `customer_id` (link to an existing customer) or
                  `customer_data` (create a customer inline). The customer
                  must belong to the same brand as the supplied
                  `membership_type_id`.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              site_id:
                type: string
                description: The site ID which this membership belongs to
                example: 000000-000000-000000-000000
              customer_data:
                type: object
                description: |
                  Inline customer data to create a new customer with the membership. See `createCustomer` for the
                  full list of accepted fields.
                additionalProperties: true
              membership_type_id:
                type: string
                description: The membership type ID. This must belong to the same brand as the given customer.
                example: 000000-000000-000000-000000
              membership_rate_id:
                type: string
                description: The membership rate ID. This must belong to the same type as provided.
                example: 000000-000000-000000-000000
              intake_form_required:
                type: boolean
                description: Whether an intake form is required for this membership
                example: true
              basket_id:
                type: string
                description: The basket ID which was used to purchase this membership, if applicable.
                example: 60c0c01d92ec44e252235966
              source:
                type: string
                description: The source of where this membership was created.
                enum:
                  - app
                  - self_signup
              external_ref:
                type: string
                description: |
                  Free-form identifier for cross-referencing this
                  membership with an external system (e.g. a legacy CRM
                  record number). Returned verbatim on `getMembership`
                  and not interpreted by the platform.
                example: legacy-crm-7421
              start_date:
                type: string
                format: date
                description: The date which the membership should start from.
                example: '2021-01-01'
              end_date:
                type: string
                format: date
                description: The date which the membership should end.
                nullable: true
                example: '2022-01-01'
            required:
              - membership_type_id
              - membership_rate_id
              - start_date
              - end_date
    UpdateMembership:
      description: Details to update the membership with.
      content:
        application/json:
          schema:
            title: UpdateMembership
            type: object
            additionalProperties: false
            properties:
              membership_type_id:
                type: string
                description: The membership type ID. This must belong to the same brand as the given customer.
                example: 000000-000000-000000-000000
              membership_rate_id:
                type: string
                description: The membership rate ID. This must belong to the same type as provided.
                example: 000000-000000-000000-000000
              start_date:
                type: string
                format: date
                description: The date which the membership should start from.
                example: '2021-01-01'
              end_date:
                type: string
                format: date
                description: The date which the membership should end.
                nullable: true
                example: '2022-01-01'
              external_ref:
                type: string
                description: |
                  Free-form identifier for cross-referencing this
                  membership with an external system (e.g. a legacy CRM
                  record number). Returned verbatim on `getMembership`
                  and not interpreted by the platform.
                example: legacy-crm-7421
    CreateMembershipType:
      content:
        application/json:
          schema:
            title: CreateMembershipType
            type: object
            additionalProperties: false
            properties:
              brand_id:
                type: string
                description: |
                  Identifier of the brand that owns this membership type.
                  Membership types are scoped per brand so customers can
                  be enrolled into the same tier across every site that
                  shares the brand.
                format: uuid
              name:
                type: string
                description: |
                  Display name of the membership tier, shown to customers
                  on the storefront, in the membership area, and on email
                  receipts. 1-120 characters and must not contain HTML.
                example: Gold tier
              description:
                type: string
                description: |
                  Marketing description of the membership tier, shown on
                  the storefront purchase page. Use it to summarise the
                  benefits of joining. Plain text, up to 1000 characters.
                example: Enjoy exclusive benefits as part of being a member in our Gold tier
                nullable: true
              terms:
                type: string
                description: Terms and conditions of the membership type
                nullable: true
                example: |
                  Membership is non-transferable and subject to a 30-day notice
                  period for cancellation. See https://example.com/terms for the
                  full agreement.
              private:
                type: boolean
                deprecated: true
                description: |
                  Whether this `MembershipType` is private or not.

                  When a `MembershipType` is private, it won't be shown to users on the site's shop frontend.

                  This field is deprecated and has been superceded by `visibility`.
              visibility:
                type: string
                description: |
                  The visibility of the `MembershipType` on the site's shop frontend.
                enum:
                  - public
                  - private
                  - link_only
              offline_payments:
                type: boolean
                description: |
                  Whether this MembershipType takes "offline" payments. If true, the monthly fee won't automatically be collected
                  using Stripe, which can be useful if a different provider is used for collecting direct debits. You'll need to
                  manually manage the membership status.
              disable_confirmation_email:
                type: boolean
                description: |
                  Whether to disable sending the confirmation email when a membership is confirmed.
              minimum_start_date:
                type: string
                format: date-time
                description: The minimum start date for a membership of this type.
                nullable: true
              min_members:
                type: integer
                description: The minimum number of members required to create a membership of this type
                example: 2
              max_members:
                type: integer
                description: The maximum number of members allowed to create a membership of this type
                example: 4
              revenue_schedule:
                type: string
                description: |
                  The revenue schedule for the membership type.
                enum:
                  - FREQ=DAILY
                  - FREQ=WEEKLY
                  - FREQ=MONTHLY;BYMONTHDAY=1
              initial_rate:
                type: object
                description: |
                  The initial rate to create for the membership type.
                title: CreateInitialRate
                additionalProperties: false
                properties:
                  processors:
                    type: array
                    description: |
                      The payment processors that can be used to process payments for this rate.
                    items:
                      type: string
                      enum:
                        - stripe
                        - adyen
                  amount:
                    type: integer
                    description: The amount to charge for the initial rate, as an integer of the smallest unit of the currency
                    example: 1000
                  currency:
                    type: string
                    description: The currency of the initial rate
                    example: GBP
                  billing_frequency:
                    type: string
                    description: |
                      The billing frequency of the initial rate in ISO 8601 duration format.
                    enum:
                      - P1M
                      - P3M
                      - P6M
                      - P1Y
                  default_duration:
                    type: string
                    description: |
                      The default duration memberships of this rate will be created with, in ISO 8601 duration format.
                    enum:
                      - P1M
                      - P3M
                      - P6M
                      - P1Y
                required:
                  - amount
                  - currency
                  - billing_frequency
            required:
              - name
              - brand_id
              - initial_rate
    UpdateMembershipType:
      content:
        application/json:
          schema:
            title: UpdateMembershipType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the membership tier, shown to customers
                  on the storefront, in the membership area, and on email
                  receipts. 1-120 characters and must not contain HTML.
                example: Gold tier
              description:
                type: string
                description: |
                  Marketing description of the membership tier, shown on
                  the storefront purchase page. Use it to summarise the
                  benefits of joining. Plain text, up to 1000 characters.
                example: Enjoy exclusive benefits as part of being a member in our Gold tier
                nullable: true
              terms:
                type: string
                description: Terms and conditions of the membership type
                nullable: true
                example: |
                  Membership is non-transferable and subject to a 30-day notice
                  period for cancellation. See https://example.com/terms for the
                  full agreement.
              private:
                type: boolean
                deprecated: true
                description: |
                  Whether this `MembershipType` is private or not.

                  When a `MembershipType` is private, it won't be shown to users on the site's shop frontend.

                  This field is deprecated and has been superceded by `visibility`.
              visibility:
                type: string
                description: |
                  The visibility of the `MembershipType` on the site's shop frontend.
                enum:
                  - public
                  - private
                  - link_only
              offline_payments:
                type: boolean
                description: |
                  Whether this MembershipType takes "offline" payments. If true, the monthly fee won't automatically be collected
                  using Stripe, which can be useful if a different provider is used for collecting direct debits. You'll need to
                  manually manage the membership status.
              disable_confirmation_email:
                type: boolean
                description: |
                  Whether to disable sending the confirmation email when a membership is confirmed.
              minimum_start_date:
                type: string
                format: date-time
                description: The minimum start date for a membership of this type.
                nullable: true
              min_members:
                type: integer
                description: The minimum number of members required to create a membership of this type
                example: 2
              max_members:
                type: integer
                description: The maximum number of members allowed to create a membership of this type
                example: 4
              revenue_schedule:
                type: string
                description: |
                  The revenue schedule for the membership type.
                enum:
                  - FREQ=DAILY
                  - FREQ=WEEKLY
                  - FREQ=MONTHLY;BYMONTHDAY=1
    CopyMembershipType:
      description: Copy a MembershipType
      content:
        application/json:
          schema:
            type: object
            title: CopyMembershipType
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name to give the duplicated membership tier.
                  The new tier inherits the source tier's pricing,
                  visibility, and benefits; the name distinguishes the
                  copy from the original. 1-120 characters.
                example: Gold tier
            required:
              - name
    UpdateMembershipTypeLocaleStrings:
      description: Update locale strings for a MembershipType
      required: true
      content:
        application/json:
          schema:
            title: UpdateMembershipTypeLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this membership type in the given locale.
                example: Spa Membership
              description:
                type: string
                nullable: true
                description: The localised description HTML for this membership type in the given locale.
                example: <p>Enjoy exclusive access to our spa facilities.</p>
              terms:
                type: string
                nullable: true
                description: The localised terms and conditions HTML for this membership type in the given locale.
                example: <p>Membership is non-transferable and subject to our standard terms.</p>
    CreateMembershipRate:
      description: Details of the membership rate to create.
      content:
        application/json:
          schema:
            title: CreateMembershipRate
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Operator-facing label for the rate. Shown alongside the
                  membership type when staff issue or amend memberships.
                  Common values include `Standard rate`, `Concession` and
                  `Founder`.
                example: Standard rate
              membership_type_id:
                type: string
                description: |
                  The `MembershipType` this rate belongs to. A
                  `MembershipRate` is always scoped to a single type and
                  cannot be moved between types after it has been used on
                  live memberships.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              price:
                type: integer
                description: |
                  The price of the rate as an integer of the smallest unit eg pence. This is charged to the
                  customer every billing period according to the `billing_frequency`.
                example: 5000
              currency:
                type: string
                description: The currency of the price, uppercase, in the ISO4217 format
                example: GBP
              joining_fee:
                type: integer
                description: The price of the joining fee as an integer of the smallest unit (eg pence).
                example: 1000
              private:
                type: boolean
                description: Whether this rate is private
                example: true
              billing_frequency:
                type: string
                description: |
                  The frequency that this membership is billed.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                example: P1M
              processors:
                type: array
                description: The payment processors that can be used to process payments for this rate.
                items:
                  type: string
                  description: The name of the processor to use for this rate
              default_duration:
                type: string
                nullable: true
                description: |
                  The default duration of the membership. This is used when a customer signs themselves up
                  for a membership. The duration is specified as an ISO8601 duration string. When null, by
                  default the membership won't end.
                example: P1Y
              notice_period:
                type: string
                nullable: true
                enum:
                  - P7D
                  - P14D
                  - P1M
                  - P3M
                  - P6M
                  - P1Y
                  - null
                description: |
                  How much notice a customer must give to cancel a membership on this rate.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                  When null, no notice is required.
                example: P1M
            required:
              - membership_type_id
              - name
              - price
              - billing_frequency
    CreateMembershipCreditRule:
      description: Create a membership credit rule for a membership type
      content:
        application/json:
          schema:
            type: object
            title: CreateMembershipCreditRule
            additionalProperties: false
            properties:
              membership_type_id:
                type: string
                format: uuid
                description: |
                  Identifier of the membership tier whose members will
                  receive this credit rule. Rules are scoped to a single
                  tier; create separate rules per tier if benefits differ.
              coupon_id:
                type: string
                description: |
                  Identifier of the coupon template used when issuing the
                  credit. Each application of the rule issues a fresh
                  coupon code derived from this template; the template
                  defines the discount amount, validity, and offerings.
                example: 5f1234567890abcdef123456
              coupon_name:
                type: string
                description: |
                  Display name shown alongside the issued coupon in the
                  customer's account (e.g. "August spa credit"). Not the
                  redemption code; that's generated automatically.
                  1-120 characters.
                example: Monthly spa credit
              roll_over:
                type: boolean
                description: |
                  If true, unused credits will roll over to the next month.
                  Otherwise, any unused credits will be marked as expired on the next billing period.
              issue_on_signup:
                type: boolean
                description: |
                  If true, the credit will be issued when new customers sign up for the given membership type.
                  Otherwise, the credit will be issued only on the monthly billing schedule.
              multi_use:
                type: boolean
                description: |
                  If true, the credit can be used an unlimited number of times until the expiry date.
              for_lead_booker_only:
                type: boolean
                description: |
                  If true, the credit will only be issued for the lead booker of an order. If false, the credit will be issued for all guests on the order, including non-members.
              issuing_frequency:
                type: string
                enum:
                  - billing_cycle
                  - P0D
                  - P1M
                  - P3M
                  - P6M
                  - P1Y
                description: |
                  The frequency that this credit is issued.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
              include_upcoming:
                type: boolean
                description: |
                  When true, apply the new rule to membership charges that
                  are already scheduled but not yet billed — issuing the
                  configured credit on the next cycle for members who
                  joined before the rule existed. When false (default), the
                  rule only takes effect for cycles scheduled after the
                  rule was created; existing scheduled charges continue
                  unchanged.
            required:
              - membership_type_id
              - coupon_id
              - coupon_name
    UpdateMembershipCreditRule:
      description: Update a membership credit rule for a membership type
      content:
        application/json:
          schema:
            type: object
            title: UpdateMembershipCreditRule
            additionalProperties: false
            properties:
              membership_type_id:
                type: string
                format: uuid
                description: |
                  Identifier of the membership tier whose members will
                  receive this credit rule. Rules are scoped to a single
                  tier; create separate rules per tier if benefits differ.
              coupon_id:
                type: string
                description: |
                  Identifier of the coupon template used when issuing the
                  credit. Each application of the rule issues a fresh
                  coupon code derived from this template; the template
                  defines the discount amount, validity, and offerings.
                example: 5f1234567890abcdef123456
              coupon_name:
                type: string
                description: |
                  Display name shown alongside the issued coupon in the
                  customer's account (e.g. "August spa credit"). Not the
                  redemption code; that's generated automatically.
                  1-120 characters.
                example: Monthly spa credit
              roll_over:
                type: boolean
                description: |
                  If true, unused credits will roll over to the next month.
                  Otherwise, any unused credits will be marked as expired on the next billing period.
              issue_on_signup:
                type: boolean
                description: |
                  If true, the credit will be issued when new customers sign up for the given membership type.
                  Otherwise, the credit will be issued only on the monthly billing schedule.
              multi_use:
                type: boolean
                description: |
                  If true, the credit can be used an unlimited number of times until the expiry date.
              for_lead_booker_only:
                type: boolean
                description: |
                  If true, the credit will only be issued for the lead booker of an order. If false, the credit will be issued for all guests on the order, including non-members.
              issuing_frequency:
                type: string
                enum:
                  - billing_cycle
                  - P0D
                  - P1M
                  - P3M
                  - P6M
                  - P1Y
                description: |
                  The frequency that this credit is issued.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
              include_upcoming:
                type: boolean
                description: |
                  When true, apply the updated rule to membership charges
                  that are already scheduled but not yet billed — picking
                  up rate / frequency / coupon changes for the next cycle
                  without waiting for the new rule to organically take
                  effect on the cycle after that. When false (default),
                  the update only affects credits issued from the next
                  billing cycle onwards; existing scheduled charges
                  continue to apply the previous rule.
    AddMembershipChargePayment:
      content:
        application/json:
          schema:
            title: AddMembershipChargePayment
            type: object
            additionalProperties: false
            properties:
              payment_type_id:
                type: string
                format: object-id
                description: |
                  Identifier of the custom payment type to attribute this
                  membership charge to (e.g. "BACS", "Cash on file").
                  Lets you record an offline-collected payment against a
                  membership charge for accurate reporting. The payment
                  type must belong to the same site as the membership.
              amount:
                type: integer
                nullable: true
                description: The amount of the payment
                example: 1000
            required:
              - payment_type_id
    SendMembershipSms:
      description: Send an SMS message for a membership
      content:
        application/json:
          schema:
            title: SendMembershipSms
            type: object
            additionalProperties: false
            properties:
              message_type:
                type: string
                description: The type of message to send.
                enum:
                  - billing_details_request
              always_send:
                type: boolean
                description: |
                  If true, send the SMS even if the membership already has a payment method.
                  Defaults to false.
                example: false
            required:
              - message_type
    PreviewMembershipSms:
      description: Preview an SMS message for a membership
      content:
        application/json:
          schema:
            title: PreviewMembershipSms
            type: object
            additionalProperties: false
            properties:
              message_type:
                type: string
                description: The type of the SMS message.
                enum:
                  - billing_details_request
              always_send:
                type: boolean
                description: |
                  If true, preview the SMS even if the membership already has a payment method.
                  Defaults to false.
                example: false
            required:
              - message_type
    CreateUser:
      content:
        application/json:
          schema:
            title: CreateUser
            type: object
            additionalProperties: false
            properties:
              email:
                type: string
                description: The email address of the user
                format: email
              first_name:
                type: string
                description: The user's given name. Shown in the admin UI alongside the surname and used in notification templates as the personalised greeting.
                example: Dan
              last_name:
                type: string
                description: The user's surname. Combined with `first_name` to display a full name in admin lists and email footers.
                example: Smith
              organisation_id:
                type: string
                description: |
                  Identifier of the organisation to scope this user's
                  access to. The caller must have organisation-admin
                  permissions on this organisation; the user will only see
                  sites that belong to it.
                format: uuid
              cashier_id:
                type: string
                description: |
                  Identifier of the cashier record this user is linked to.
                  Cashier IDs map operator activity (sales, refunds, till
                  opens) back to a real person for reporting and audit.
                format: uuid
            required:
              - email
              - first_name
              - last_name
    UpdateUser:
      content:
        application/json:
          schema:
            title: UpdateUser
            type: object
            additionalProperties: false
            properties:
              email:
                type: string
                description: The email address of the user
                format: email
              first_name:
                type: string
                description: The user's given name. Shown in the admin UI alongside the surname and used in notification templates as the personalised greeting.
                example: Dan
              last_name:
                type: string
                description: The user's surname. Combined with `first_name` to display a full name in admin lists and email footers.
                example: Smith
              organisation_id:
                type: string
                description: |
                  Identifier of the organisation to scope this user's
                  access to. The caller must have organisation-admin
                  permissions on this organisation; the user will only see
                  sites that belong to it.
                format: uuid
              cashier_id:
                type: string
                description: |
                  Identifier of the cashier record this user is linked to.
                  Cashier IDs map operator activity (sales, refunds, till
                  opens) back to a real person for reporting and audit.
                format: uuid
              site_ids:
                type: array
                items:
                  type: string
                  format: uuid
                description: The IDs of the sites to add the user to
    AssignRoleRequest:
      content:
        application/json:
          schema:
            title: AssignRoleRequest
            type: object
            additionalProperties: false
            properties:
              role_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation role to assign or remove.
                  Roles grant a bundle of permissions across the user's
                  organisation; for per-site permissions use the
                  `site-roles` endpoint instead.
            required:
              - role_id
    RemoveRoleRequest:
      content:
        application/json:
          schema:
            title: RemoveRoleRequest
            type: object
            additionalProperties: false
            properties:
              role_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation role to assign or remove.
                  Roles grant a bundle of permissions across the user's
                  organisation; for per-site permissions use the
                  `site-roles` endpoint instead.
            required:
              - role_id
    CreateRole:
      content:
        application/json:
          schema:
            title: CreateRole
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the role, shown in the admin UI when
                  managing user permissions. Pick a name that summarises
                  the role's responsibilities (e.g. "Spa Manager").
                  1-120 characters.
                example: Spa Manager
              organisation_id:
                type: string
                format: uuid
                description: |
                  Identifier of the organisation that owns this role.
                  Roles are scoped per organisation so each customer can
                  define its own permission bundles; the role can be
                  assigned to any user in the same organisation.
            required:
              - name
              - organisation_id
    UpdateRole:
      description: Update a Role
      content:
        application/json:
          schema:
            title: UpdateRole
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the role, shown in the admin UI when
                  managing user permissions. Pick a name that summarises
                  the role's responsibilities (e.g. "Spa Manager").
                  1-120 characters.
                example: Spa Manager
              description:
                type: string
                description: |
                  Free-text description of what the role is for, shown
                  underneath the role name in the admin UI. Use it to
                  record the scope and intent of the permission bundle.
                  Plain text, up to 500 characters.
                example: Allows access to settings for the assigned site.
                nullable: true
              permissions:
                type: array
                description: The permissions assigned to this role.
                nullable: true
                items:
                  type: string
                  example: clients.view
    CopyRole:
      description: Copy a Role
      content:
        application/json:
          schema:
            type: object
            title: CopyRole
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the duplicated role. The new role
                  inherits the source role's permissions and description;
                  the name distinguishes the copy from the original.
                  1-120 characters.
                example: Spa Manager
            required:
              - name
    CreateCommissionPackage:
      content:
        application/json:
          schema:
            title: CreateCommissionPackage
            allOf:
              - $ref: '#/components/schemas/UpdateCommissionPackage-content-application~1json-schema'
              - type: object
                required:
                  - name
                  - default_evaluation_period
    UpdateCommissionPackage:
      content:
        application/json:
          schema:
            type: object
            title: UpdateCommissionPackage
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the commission package, shown in the
                  admin UI when assigning packages to practitioners and on
                  commission reports. Pick a name that summarises the
                  package's rate structure. 1-120 characters.
                example: Senior Therapist Package
              default_evaluation_period:
                description: |
                  The default period over which commission earned under this
                  package is aggregated and paid out. Determines whether
                  targets and tiers reset weekly, monthly, etc. Accepts the
                  `EvaluationPeriod` enum values.
                allOf:
                  - $ref: '#/components/schemas/EvaluationPeriod'
              week_starts_on:
                description: |
                  The day a `weekly` or `bi_weekly` evaluation period
                  starts on. Omit or send `null` to default to `monday`.
                allOf:
                  - $ref: '#/components/schemas/DayOfWeek'
                  - type: string
                    nullable: true
                    example: monday
              requested_surcharge_percentage:
                type: number
                description: An optional surcharge percentage applied to requested practitioner bookings.
                example: 5
                nullable: true
              rates:
                type: array
                description: The commission rates for this package.
                items:
                  $ref: '#/components/schemas/CreateCommissionPackageRate'
    CreateUserCommissionAssignment:
      description: |
        Body for assigning a `CommissionPackage` to a `User` at a site. The
        combination of `user_id` and `site_id` must be unique — reassigning
        a user's package at a site requires updating the existing
        `UserCommissionAssignment` instead of creating a new one.
      required: true
      content:
        application/json:
          schema:
            title: CreateUserCommissionAssignment
            type: object
            additionalProperties: false
            properties:
              user_id:
                type: string
                format: uuid
                description: The ID of the `User` to assign the commission package to.
              site_id:
                type: string
                format: mongo-id
                description: The ID of the site this assignment applies to.
              commission_package_id:
                type: string
                format: mongo-id
                description: The ID of the `CommissionPackage` to assign.
            required:
              - user_id
              - site_id
              - commission_package_id
    UpdateUserCommissionAssignment:
      description: |
        Body for updating an existing `UserCommissionAssignment`. Only the
        assigned `CommissionPackage` can be changed; to move the
        assignment to a different user or site, delete it and create a
        new one.
      required: true
      content:
        application/json:
          schema:
            title: UpdateUserCommissionAssignment
            type: object
            additionalProperties: false
            properties:
              commission_package_id:
                type: string
                format: mongo-id
                description: The ID of the `CommissionPackage` to assign.
            required:
              - commission_package_id
    CreateOfferingSet:
      content:
        application/json:
          schema:
            title: CreateOfferingSet
            allOf:
              - $ref: '#/components/schemas/UpdateOfferingSet-content-application~1json-schema'
              - type: object
                required:
                  - name
    UpdateOfferingSet:
      content:
        application/json:
          schema:
            type: object
            title: UpdateOfferingSet
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name of the offering set, shown in the admin UI
                  when picking a set to apply (e.g. as a coupon restriction
                  or to scope a commission rate). Offering sets are reusable
                  groupings of treatments, classes, or products.
                  1-120 characters.
                example: Massage treatments
              offerings:
                type: array
                description: The offerings that belong to this set.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
    CreateAppointmentTag:
      description: |
        To create an appointment tag, pass an object containing the tag's
        display `name`. The tag will be created against the organisation
        identified in the URL and will be available immediately to every
        site under that organisation.
      required: true
      content:
        application/json:
          schema:
            title: CreateAppointmentTag
            type: object
            additionalProperties: false
            required:
              - name
            properties:
              name:
                type: string
                description: |
                  Display name of the tag, shown to staff in the admin UI
                  and used when grouping appointment types in reports.
                  1-120 characters; must not contain HTML.
                example: Signature
    CreateOrganisationLabel:
      description: |
        To create a label, pass an object containing the label's display
        `name`, optional `color`, and the `site_ids` it should be visible
        to. The label will be created against the organisation identified
        in the URL.
      required: true
      content:
        application/json:
          schema:
            title: CreateOrganisationLabel
            type: object
            additionalProperties: false
            required:
              - name
              - site_ids
            properties:
              name:
                type: string
                maxLength: 40
                description: |
                  Display name of the label. 1-40 characters; must not
                  contain HTML.
                example: VIP
              color:
                type: string
                pattern: ^#[0-9a-f]{6}$
                nullable: true
                description: |
                  Hex colour used to render the label in the admin UI,
                  including the leading `#`. Lower-case hexadecimal; must
                  match `#rrggbb`. Defaults to `#f1f1f1` when omitted.
                example: '#ff5733'
              site_ids:
                type: array
                description: |
                  Identifiers of the sites within the organisation that
                  should be allowed to see and apply this label. Every
                  site ID must belong to the same organisation as the
                  label.
                items:
                  type: string
                  format: uuid
                example:
                  - 65a0c2e5b3a7d2f8c1d4e7ba
    UpdateOrganisationLabel:
      description: |
        Update an existing label. Any field that is omitted will be left
        unchanged. `site_ids` is required and replaces the existing list
        of sites the label is visible to.
      required: true
      content:
        application/json:
          schema:
            title: UpdateOrganisationLabel
            type: object
            additionalProperties: false
            required:
              - site_ids
            properties:
              name:
                type: string
                maxLength: 40
                description: |
                  Display name of the label. 1-40 characters; must not
                  contain HTML.
                example: VIP
              color:
                type: string
                pattern: ^#[0-9a-f]{6}$
                nullable: true
                description: |
                  Hex colour used to render the label in the admin UI,
                  including the leading `#`. Lower-case hexadecimal; must
                  match `#rrggbb`.
                example: '#ff5733'
              site_ids:
                type: array
                description: |
                  Identifiers of the sites within the organisation that
                  should be allowed to see and apply this label. Every
                  site ID must belong to the same organisation as the
                  label. The provided list replaces any previously stored
                  list.
                items:
                  type: string
                  format: uuid
                example:
                  - 65a0c2e5b3a7d2f8c1d4e7ba
    CreateSalesChannel:
      description: |
        To create a sales channel, pass an object containing the channel's
        display `name`. The channel will be created against the organisation
        identified in the URL and will be immediately available across the
        organisation for tagging orders, appointments, and other revenue
        records.
      required: true
      content:
        application/json:
          schema:
            title: CreateSalesChannel
            type: object
            additionalProperties: false
            required:
              - name
            properties:
              name:
                type: string
                description: |
                  Display name of the sales channel, shown in pickers
                  across the admin UI and on reports that break revenue
                  down by channel.
                example: Front Desk
    CreatePackageAvailabilityRule:
      description: |
        Body for creating a new `AvailabilityRule` on a `Package`. Only
        `is_available` is required; the remaining fields filter when the
        rule applies. Sending no filters creates a rule that applies always.
      required: true
      content:
        application/json:
          schema:
            title: CreatePackageAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: |
                  When true, this rule opens bookable windows for the
                  package. When false, it closes them. Any `false` rule
                  overrides any `true` rule for the same time period.
                example: false
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date this rule applies (inclusive). Defaults to today
                  in the package's timezone when omitted.
                example: '2026-12-24'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date this rule applies (inclusive). When omitted, the
                  rule has no end date.
                example: '2026-12-26'
              time_from:
                type: string
                nullable: true
                description: |
                  Start of the daily time window in 24-hour `HH:MM` format.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: |
                  End of the daily time window in 24-hour `HH:MM` format.
                example: '18:00'
              min_duration:
                type: integer
                minimum: 1
                nullable: true
                description: |
                  Match the rule only when the package's total duration is
                  ≥ this many minutes. Omit to apply to any duration.
                example: 60
              max_duration:
                type: integer
                minimum: 1
                nullable: true
                description: |
                  Match the rule only when the package's total duration is
                  ≤ this many minutes.
                example: 240
              weekdays:
                type: array
                description: |
                  Days of the week the rule applies on. Empty / omitted means
                  every day.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - saturday
                  - sunday
            required:
              - is_available
    UpdatePackageAvailabilityRule:
      description: |
        Body for updating an existing `AvailabilityRule` on a `Package`.
        The server validates the same shape as on create, so `is_available`
        is required. Every other field is optional and overrides the
        current value when sent.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePackageAvailabilityRule
            type: object
            additionalProperties: false
            properties:
              is_available:
                type: boolean
                description: Whether the window is bookable. `false` rules override `true` rules.
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-12-24'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-12-26'
              time_from:
                type: string
                nullable: true
                description: Daily start time in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: Daily end time in `HH:MM`.
                example: '18:00'
              min_duration:
                type: integer
                minimum: 1
                nullable: true
                description: Match only for total package durations ≥ this many minutes.
                example: 60
              max_duration:
                type: integer
                minimum: 1
                nullable: true
                description: Match only for total package durations ≤ this many minutes.
                example: 240
              weekdays:
                type: array
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
            required:
              - is_available
    CreatePackageItemChoice:
      description: |
        Body for creating a new `PackageItemChoice` on a `Package`. At
        minimum, provide a `name`, an `offering_type`, and the `options`
        the customer can pick from. All other fields tune how the choice
        behaves in the booking flow.
      required: true
      content:
        application/json:
          schema:
            title: CreatePackageItemChoice
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: A short, customer-facing label for the choice.
                example: Massage
              description:
                type: string
                nullable: true
                description: A longer explanation rendered alongside the options at booking time.
                example: Choose your type of massage.
              min_options:
                type: integer
                minimum: 0
                nullable: true
                description: |
                  Minimum number of options the customer must pick. Defaults
                  to `1` (or `0` when `optional` is true) when omitted.
                example: 1
              max_options:
                type: integer
                minimum: 0
                nullable: true
                description: |
                  Maximum number of options the customer may pick. Defaults
                  to `1` when omitted. With `max_options: 1` any
                  `option_budget` is ignored.
                example: 1
              option_budget:
                type: integer
                minimum: 0
                nullable: true
                description: |
                  An "included" budget for the chosen options in the smallest
                  currency unit. Each option uses its standalone price; the
                  overall package price is bumped up by any excess over this
                  budget.
                example: 6000
              auto_select_timeslot:
                type: boolean
                description: |
                  When true, the booking engine auto-picks a timeslot for
                  this choice instead of asking the customer. Only allowed
                  when `offering_type` is `appointment`.
                example: false
              hide_times:
                type: boolean
                description: Hide individual option start times from the customer-facing booking flow.
                example: false
              allocation:
                type: object
                nullable: true
                title: CreatePackageItemChoiceAllocation
                additionalProperties: false
                description: |
                  An accounting allocation for this choice — splits the
                  choice's portion of the package revenue into a named
                  revenue centre at a fixed amount.
                properties:
                  revenue_centre:
                    type: string
                    description: The revenue centre's identifier.
                    example: treatments
                  amount:
                    type: integer
                    minimum: 0
                    description: The allocated amount in the smallest currency unit.
                    example: 4000
              optional:
                type: boolean
                description: Whether the customer can skip this choice entirely.
                example: false
              visible:
                type: boolean
                description: Whether the choice is visible to the customer. Hidden choices are only allowed for `product` offering types.
                example: true
              offering_type:
                type: string
                description: |
                  The type of offerings this choice's options reference.
                  Only one `hotel_room_reservation` choice is allowed per
                  package.
                enum:
                  - appointment
                  - area_booking
                  - hotel_room_reservation
                  - product
                  - session
                  - table_reservation
                example: appointment
              options:
                type: array
                description: |
                  The list of selectable options. Each option references an
                  offering on the package's site; the option's `item_type`
                  must match this choice's `offering_type`.
                items:
                  title: CreatePackageItemChoiceOption
                  type: object
                  additionalProperties: false
                  required:
                    - id
                    - item_type
                  properties:
                    id:
                      type: string
                      description: The ID of the offering this option references.
                      example: 5dcb47800000000000000026
                    item_type:
                      type: string
                      description: Must match the choice's `offering_type`.
                      enum:
                        - appointment
                        - area_booking
                        - hotel_room_reservation
                        - product
                        - session
                        - table_reservation
                      example: appointment
                    price_change:
                      type: integer
                      nullable: true
                      description: A delta applied to the package price when this option is chosen, in the smallest currency unit.
                      example: 2000
    UpdatePackageItemChoice:
      description: |
        Body for updating a `PackageItemChoice`. Every field is optional;
        only fields you send are written. Updates that change `offering_type`
        must also re-send `options` so each option's `item_type` continues
        to match.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePackageItemChoice
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: A short, customer-facing label for the choice.
                example: Massage
              description:
                type: string
                nullable: true
                description: A longer explanation rendered alongside the options at booking time.
                example: Choose your type of massage.
              min_options:
                type: integer
                minimum: 0
                description: Minimum number of options the customer must pick.
                example: 1
              max_options:
                type: integer
                minimum: 0
                nullable: true
                description: |
                  Maximum number of options the customer may pick. With
                  `max_options: 1` any `option_budget` is dropped.
                example: 2
              option_budget:
                type: integer
                minimum: 0
                nullable: true
                description: Included budget for the chosen options in the smallest currency unit.
                example: 6000
              auto_select_timeslot:
                type: boolean
                description: Whether the booking engine should auto-pick a timeslot for this choice.
              hide_times:
                type: boolean
                description: Hide individual option start times from the customer-facing booking flow.
              allocation:
                type: object
                nullable: true
                title: UpdatePackageItemChoiceAllocation
                additionalProperties: false
                description: |
                  An accounting allocation for this choice. Send `null`
                  fields to clear the existing allocation.
                properties:
                  revenue_centre:
                    type: string
                    nullable: true
                    description: The revenue centre's identifier.
                    example: treatments
                  amount:
                    type: integer
                    minimum: 0
                    nullable: true
                    description: The allocated amount in the smallest currency unit.
                    example: 4000
              optional:
                type: boolean
                description: Whether the customer can skip this choice entirely.
              visible:
                type: boolean
                description: |
                  Whether the choice is visible to the customer. Setting
                  `visible: false` is only allowed when `offering_type`
                  is `product`; other types return `400`.
              offering_type:
                type: string
                description: The type of offerings this choice's options reference.
                enum:
                  - appointment
                  - area_booking
                  - hotel_room_reservation
                  - product
                  - session
                  - table_reservation
              start_time_rules:
                type: array
                description: |
                  Rules restricting which start times are offered for this
                  choice's options. Each rule is either `absolute` (fixed
                  `HH:MM` window) or `relative` (offset in minutes from a
                  base point such as the start of the package's first item).
                items:
                  title: UpdatePackageItemChoiceStartTimeRule
                  type: object
                  additionalProperties: false
                  required:
                    - type
                  properties:
                    type:
                      type: string
                      enum:
                        - absolute
                        - relative
                      description: |
                        `absolute` constrains the start time to a fixed
                        `HH:MM` window; `relative` to an offset (in
                        minutes) from `relative_to`.
                      example: relative
                    relative_to:
                      type: string
                      nullable: true
                      enum:
                        - first_item_start
                      description: |
                        Required when `type` is `relative`. The base time
                        the offsets are calculated from.
                    relative_mins_from:
                      type: integer
                      minimum: 0
                      nullable: true
                      description: Earliest offset (minutes) from `relative_to`.
                      example: 0
                    relative_mins_to:
                      type: integer
                      minimum: 0
                      nullable: true
                      description: |
                        Latest offset (minutes) from `relative_to`. Must be
                        ≥ `relative_mins_from`.
                      example: 30
                    absolute_time_from:
                      type: string
                      nullable: true
                      description: |
                        Required when `type` is `absolute`. The earliest
                        allowed start time in 24-hour `HH:MM` format.
                      example: '12:00'
                    absolute_time_to:
                      type: string
                      nullable: true
                      description: |
                        Required when `type` is `absolute`. The latest
                        allowed start time in 24-hour `HH:MM` format.
                      example: '12:30'
              allow_overlaps:
                type: boolean
                description: |
                  Allow this choice's items to overlap with other items
                  even when `prevent_choice_overlaps` is true on the parent
                  package. Has no effect unless the package opts in to
                  overlap prevention.
              options:
                type: array
                description: |
                  The list of selectable options. At least one option is
                  required unless `offering_type` is `hotel_room_reservation`.
                  Each option's `item_type` must match `offering_type`.
                items:
                  title: UpdatePackageItemChoiceOption
                  type: object
                  additionalProperties: false
                  required:
                    - id
                    - item_type
                  properties:
                    id:
                      type: string
                      description: The ID of the offering this option references.
                      example: 5dcb47800000000000000026
                    item_type:
                      type: string
                      description: Must match the choice's `offering_type`.
                      enum:
                        - appointment
                        - area_booking
                        - hotel_room_reservation
                        - product
                        - session
                        - table_reservation
                    price_change:
                      type: integer
                      nullable: true
                      description: A delta applied to the package price when this option is chosen, in the smallest currency unit.
                      example: 2000
              choice_configuration:
                type: object
                additionalProperties: true
                description: Free-form additional configuration for the choice. Shape depends on `offering_type`.
    CreatePackagePriceRule:
      description: |
        Body for creating a new `PriceRule` on a `Package`. Only `price` is
        strictly required; all other fields are filters that restrict when
        the rule applies. With no filters, the rule applies to every booking
        of this package (useful as the package's default fallback price).
      required: true
      content:
        application/json:
          schema:
            title: CreatePackagePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: |
                  Price in the smallest currency unit (e.g. pence, cents).
                  `20000` means £200.00 in a GBP-denominated site.
                example: 20000
              date_from:
                type: string
                format: date
                nullable: true
                description: |
                  First date this rule applies (inclusive). Defaults to today
                  in the site's timezone when omitted.
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: |
                  Last date this rule applies (inclusive). When omitted, the
                  rule has no end date.
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: |
                  Start of the time-of-day window in 24-hour `HH:MM` format.
                  When `time_to` is set, must be earlier than `time_to`
                  (the rule does not wrap past midnight).
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: |
                  End of the time-of-day window in 24-hour `HH:MM` format.
                  Must be later than `time_from` if both are set.
                example: '14:00'
              weekdays:
                type: array
                description: |
                  Days of the week this rule applies on. Empty / omitted means
                  every day.
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
                example:
                  - saturday
                  - sunday
            required:
              - price
    UpdatePackagePriceRule:
      description: |
        Body for updating an existing `PriceRule` on a `Package`. The same
        validator runs on create + update server-side, so `price` is
        required. Every other field is optional; only fields you send are
        written.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePackagePriceRule
            type: object
            additionalProperties: false
            properties:
              price:
                type: integer
                minimum: 0
                description: Price in the smallest currency unit.
                example: 20000
              date_from:
                type: string
                format: date
                nullable: true
                description: First date this rule applies (inclusive).
                example: '2026-06-01'
              date_to:
                type: string
                format: date
                nullable: true
                description: Last date this rule applies (inclusive).
                example: '2026-08-31'
              time_from:
                type: string
                nullable: true
                description: Start of the time-of-day window in `HH:MM`.
                example: '10:00'
              time_to:
                type: string
                nullable: true
                description: End of the time-of-day window in `HH:MM`.
                example: '14:00'
              weekdays:
                type: array
                items:
                  type: string
                  enum:
                    - monday
                    - tuesday
                    - wednesday
                    - thursday
                    - friday
                    - saturday
                    - sunday
            required:
              - price
    CreateBlockedTimePreset:
      description: |
        Body for creating a new `BlockedTimePreset`. `name` is required;
        every other field is optional and falls back to the platform
        default for blocked times.
      required: true
      content:
        application/json:
          schema:
            title: CreateBlockedTimePreset
            type: object
            additionalProperties: false
            required:
              - name
            properties:
              name:
                type: string
                description: Display name. Plain text only.
                example: Lunch break
              duration:
                type: integer
                minimum: 1
                maximum: 1200
                description: |
                  Default duration in minutes (1..1200). Defaults to the
                  site's calendar slot duration when omitted.
                example: 30
              type:
                type: string
                enum:
                  - cleaning
                  - break
                  - meeting
                  - other
                description: Default block type. Drives the calendar icon.
              label:
                type: string
                nullable: true
                description: |
                  Default short label rendered on the calendar tile so
                  staff can distinguish blocks at a glance (e.g. `Lunch`
                  or `Team meeting`). Plain text only.
                example: Lunch
              notes:
                type: string
                nullable: true
                description: |
                  Default free-form note (plain text) shown when staff
                  click into a block created from this preset. Useful for
                  extra context that doesn't fit on the label.
                example: Cover the front desk with reception.
              color:
                type: string
                nullable: true
                description: |
                  Default hex colour override. Format `#rrggbb`,
                  lower-case.
                example: '#ff8800'
              organisation_id:
                type: string
                format: uuid
                description: |
                  Organisation that owns this preset. Defaults to the
                  caller's default organisation. The caller must belong
                  to the chosen organisation.
    UpdateBlockedTimePreset:
      description: |
        Body for updating an existing `BlockedTimePreset`. `name` is
        required (full-replacement update semantics); other fields fall
        back to their current values when omitted.
      required: true
      content:
        application/json:
          schema:
            title: UpdateBlockedTimePreset
            type: object
            additionalProperties: false
            required:
              - name
            properties:
              name:
                type: string
                description: Display name. Plain text only.
                example: Lunch break
              duration:
                type: integer
                minimum: 1
                maximum: 1200
                description: Default duration in minutes (1..1200).
                example: 30
              type:
                type: string
                enum:
                  - cleaning
                  - break
                  - meeting
                  - other
                description: |
                  Default block type used when a new blocked-time is
                  created from this preset. Drives the calendar icon
                  and the reporting category.
              label:
                type: string
                nullable: true
                description: |
                  Default short label rendered on the calendar tile so
                  staff can distinguish blocks at a glance. Plain text
                  only.
                example: Lunch
              notes:
                type: string
                nullable: true
                description: |
                  Default free-form note (plain text) shown when staff
                  click into a block created from this preset.
                example: Cover the front desk with reception.
              color:
                type: string
                nullable: true
                description: Default hex colour (`#rrggbb`).
                example: '#ff8800'
    CopyBlockedTimePreset:
      description: |
        Body for copying a `BlockedTimePreset`. `name` is required (so
        the copy lands with a distinct display name); other overrides
        are optional and fall back to the source preset's values.
      required: true
      content:
        application/json:
          schema:
            title: CopyBlockedTimePreset
            type: object
            additionalProperties: false
            required:
              - name
            properties:
              name:
                type: string
                description: Display name for the new preset.
                example: Lunch break (covered)
              duration:
                type: integer
                minimum: 1
                maximum: 1200
                description: Override the source duration.
                example: 45
              type:
                type: string
                enum:
                  - cleaning
                  - break
                  - meeting
                  - other
                description: Override the source block type.
              label:
                type: string
                nullable: true
                description: Override the source label.
                example: Lunch
              notes:
                type: string
                nullable: true
                description: Override the source notes.
                example: Cover the front desk with reception.
              color:
                type: string
                nullable: true
                description: Override the source colour (`#rrggbb`).
                example: '#ff8800'
    CreateBlockedTime:
      description: |
        Body for creating a new `BlockedTime`. `start_time`, `end_time`,
        and `type` are required, plus at least one of
        `practitioner_ids` / `room_ids` / `area_ids` (the blocked time
        must apply to at least one calendar).

        Setting `recurrence.weekdays` fans the blocked time out across
        matching weekdays in `recurrence.date_from`..`recurrence.date_to`
        (range max 366 days). The first batch is created synchronously
        and the remainder via an async job.
      required: true
      content:
        application/json:
          schema:
            title: CreateBlockedTime
            type: object
            additionalProperties: false
            required:
              - start_time
              - end_time
              - type
            properties:
              start_time:
                type: string
                format: date-time
                description: Start of the blocked window. ISO-8601, in the site's timezone.
                example: '2026-06-01T09:00:00+01:00'
              end_time:
                type: string
                format: date-time
                description: End of the blocked window. Must be strictly after `start_time`.
                example: '2026-06-01T09:30:00+01:00'
              type:
                type: string
                enum:
                  - cleaning
                  - break
                  - meeting
                  - other
                description: The kind of block. Drives the calendar icon.
              label:
                type: string
                nullable: true
                description: Optional short label shown on the calendar tile.
                example: Lunch
              notes:
                type: string
                nullable: true
                description: Optional longer note (plain text).
                example: Cover the front desk with reception.
              color:
                type: string
                nullable: true
                description: |
                  Optional hex colour override. Format `#rrggbb`
                  (lower-case).
                example: '#ff8800'
              practitioner_ids:
                type: array
                description: |
                  Practitioners whose calendars should be blocked.
                  Required unless `room_ids` or `area_ids` is provided.
                items:
                  type: string
                  format: object-id
              room_ids:
                type: array
                description: |
                  Rooms to block. Required unless `practitioner_ids` or
                  `area_ids` is provided.
                items:
                  type: string
                  format: object-id
              area_ids:
                type: array
                description: |
                  Bookable areas to block. Required unless
                  `practitioner_ids` or `room_ids` is provided.
                items:
                  type: string
                  format: object-id
              recurrence:
                $ref: '#/components/schemas/BlockedTimeRecurrence'
    UpdateBlockedTime:
      description: |
        Body for updating an existing `BlockedTime`. Fields are
        individually optional; omitted fields keep their current values.

        Use the `old_*` / `new_*` pairs to swap a single resource
        (practitioner, room, or area) without rebuilding the full ID
        lists. When the underlying recurrence-group instance is split
        by the update, the server returns `201 Created` with the new
        blocked time; otherwise it returns `200 OK` with the same
        `BlockedTime`.
      required: true
      content:
        application/json:
          schema:
            title: UpdateBlockedTime
            type: object
            additionalProperties: false
            properties:
              start_time:
                type: string
                format: date-time
                description: |
                  New start of the blocked window. ISO-8601, in the
                  site's timezone.
              end_time:
                type: string
                format: date-time
                description: New end time. Must be strictly after `start_time`.
              type:
                type: string
                enum:
                  - cleaning
                  - break
                  - meeting
                  - other
                description: |
                  New block type. Drives the calendar icon and the
                  reporting category.
              label:
                type: string
                nullable: true
                description: |
                  Replacement short label shown on the calendar tile.
                  Pass `null` to clear.
                example: Lunch
              notes:
                type: string
                nullable: true
                description: |
                  Replacement free-form note (plain text). Pass `null`
                  to clear.
                example: Cover the front desk with reception.
              color:
                type: string
                nullable: true
                description: Updated hex colour (`#rrggbb`).
                example: '#ff8800'
              practitioner_ids:
                type: array
                description: Replace the practitioner targets.
                items:
                  type: string
                  format: object-id
              old_practitioner_id:
                type: string
                format: object-id
                description: |
                  Existing practitioner ID to swap. Used with
                  `new_practitioner_id` to update a single calendar
                  without rebuilding the list.
              new_practitioner_id:
                type: string
                format: object-id
                description: Replacement practitioner ID for the swap.
              old_room_id:
                type: string
                format: object-id
                description: Existing room ID to swap.
              new_room_id:
                type: string
                format: object-id
                description: Replacement room ID for the swap.
              old_area_id:
                type: string
                format: object-id
                description: Existing bookable-area ID to swap.
              new_area_id:
                type: string
                format: object-id
                description: Replacement bookable-area ID for the swap.
    CreateCourseType:
      description: |
        Body for creating a new `CourseType`. `name` is required;
        everything else has a sensible default or `null`-equivalent.

        `CourseType`s are prepaid packs of credits redeemable against
        appointments, sessions, area bookings, or products. The included
        offerings can be specified either:

        - As a flat list of `offerings` (each entry referencing one
          offering type + ID), or
        - For older callers, as a single `offering_type` + `offering_id`
          pair. New callers should prefer `offerings`.

        On create the server provisions an internal `Coupon` to track
        redemptions (or reuses one if `coupon_id` is supplied). Requires
        the `SETTINGS_MANAGE` permission on the site referenced via the
        `Trybe-Site-Id` header.
      required: true
      content:
        application/json:
          schema:
            title: CreateCourseType
            type: object
            additionalProperties: false
            required:
              - name
            properties:
              name:
                type: string
                description: |
                  Display name for the course type. Visible to customers
                  in the shopfront and on emailed credit balances. Plain
                  text only.
                example: 5-Pack Aromatherapy Massage
              currency:
                $ref: '#/components/schemas/properties_currency'
              description:
                type: string
                nullable: true
                description: |
                  Long-form description shown to customers when they're
                  selecting the course type. Markdown is rendered.
                example: |
                  Five 60-minute aromatherapy massages, valid for 12 months
                  from purchase. Use them whenever — no booking deadline.
              standard_price:
                type: integer
                nullable: true
                description: |
                  The standard price for this course type, in the smallest
                  currency unit (e.g. pence). Optional at create time —
                  course types can be created without a standard price and
                  have one configured later.
                example: 5000
              product_code:
                type: string
                nullable: true
                description: |
                  Optional product code used to map the course type to an
                  external POS or PMS catalog. Free-form; uniqueness is
                  not enforced.
                example: COURSE-AROMA-5
              external_id:
                type: string
                nullable: true
                description: External identifier used by integrations to reference this offering. Free-form.
                example: ext-aroma-5
              offered_online:
                type: boolean
                description: |
                  When `true`, this course type can be purchased via the
                  public shopfront. When `false` it is admin-only. Defaults
                  to `false`.
                default: false
              private:
                type: boolean
                description: |
                  When `true`, the course type is hidden from the public
                  shopfront listing but remains purchasable via direct
                  link. Used for "secret" or staff-only offers.
                default: false
              visibility:
                $ref: '#/components/schemas/visibility'
              coupon_id:
                type: string
                format: object-id
                description: |
                  Optional `Coupon` to use as the redemption-tracking
                  coupon for this course type. When omitted the server
                  creates a new programmatic coupon named "<name> credit"
                  and attaches it.
              offering_type:
                type: string
                description: |
                  Deprecated. The type of offering this course unlocks.
                  Used together with `offering_id` for legacy single-
                  offering course types. New callers should populate
                  `offerings` instead.
                enum:
                  - area_booking
                  - appointment
                  - product
                  - session
              offering_id:
                type: string
                format: object-id
                nullable: true
                description: |
                  Deprecated. The ID of the single offering this course
                  unlocks. Paired with `offering_type`. New callers should
                  populate `offerings` instead.
              offerings:
                type: array
                description: |
                  List of offerings this course type unlocks. Each entry
                  identifies one offering by type + ID. Offerings must
                  belong to the same site as the course type — others are
                  dropped at validation time.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              quantity:
                type: integer
                minimum: 1
                description: |
                  Number of credits the course grants when purchased.
                  Defaults to `1`.
                example: 5
              credits_validity_interval:
                type: string
                nullable: true
                description: |
                  ISO 8601 duration string for how long credits remain
                  redeemable from purchase. `null` means credits never
                  expire. Example: `P1Y` = 1 year, `P6M` = 6 months.
                example: P1Y
              image_id:
                type: string
                format: object-id
                nullable: true
                description: ID of an uploaded `Media` to use as the course type's hero image.
              customers_only:
                type: boolean
                description: |
                  When `true`, only signed-in customers can purchase. When
                  `false`, guest checkout is allowed.
                default: false
              members_only:
                type: boolean
                description: |
                  When `true`, only customers with an active membership of
                  one of the `permitted_membership_type_ids` can purchase.
                default: false
              upsell_offerings:
                type: array
                description: Offerings shown as upsells during checkout.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              cross_sell_offerings:
                type: array
                description: Offerings shown as cross-sells on the course type's detail page.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              related_retail_offerings:
                type: array
                description: Retail products shown as related items.
                items:
                  $ref: '#/components/schemas/OfferingIdentifier'
              permitted_membership_type_ids:
                type: array
                nullable: true
                description: |
                  When `members_only: true`, the list of `MembershipType`
                  IDs whose holders are eligible to purchase. Must belong
                  to the same brand as the course type's site.
                items:
                  type: string
                  format: uuid
              category_ids:
                type: array
                description: Category IDs the course type belongs to. Used for shopfront grouping.
                items:
                  type: string
                  format: object-id
              revenue_centre:
                type: string
                nullable: true
                description: |
                  Free-form revenue centre code for accounting reports.
                  Must be a configured revenue centre on the course type's
                  site.
                example: courses
    MultiAppointmentAvailability:
      description: |
        Body for the multi-appointment availability check. Lists every
        appointment type the customer wants to book back-to-back on the
        given `date`.

        The server tries to fit every item into a common start time at
        the given site, returning each viable arrangement as a
        `MultiAppointmentSlotGroup`. Items may carry per-item
        `duration` and `quantity` overrides.
      required: true
      content:
        application/json:
          schema:
            title: MultiAppointmentAvailability
            type: object
            additionalProperties: false
            required:
              - site_id
              - date
              - items
            properties:
              site_id:
                type: string
                description: ID of the site to search at.
                example: 5dcb47800000000000000010
              date:
                type: string
                format: date
                description: |
                  Day to slot the appointments into, ISO-8601
                  `YYYY-MM-DD` in the site's timezone.
              items:
                type: array
                description: |
                  One entry per appointment type to chain. Order
                  matters — each item slots immediately after the
                  previous one.
                minItems: 1
                items:
                  $ref: '#/components/schemas/MultiAppointmentSlotItemInput'
              practitioner_id:
                type: string
                description: |
                  Constrain every appointment to the same practitioner.
                example: 5dcb47800000000000000020
              basket_id:
                type: string
                description: |
                  Basket to exclude from the conflict calculation
                  (useful when re-checking after an edit).
                example: 60c0c01d92ec44e252235966
    CreateOrderItemPackageItem:
      required: true
      content:
        application/json:
          schema:
            title: CreateOrderItemPackageItem
            type: object
            additionalProperties: false
            properties:
              choice_id:
                type: string
                description: |
                  Identifier of the package choice the new item satisfies.
                  Choices are configured on the parent package and group
                  together the eligible options (e.g. "pick one of these
                  treatments"). Must match one of the parent package's
                  configured choice IDs.
                example: 5f1a83b9d52d5c2c8b8b4567
              option_id:
                type: string
                description: |
                  Identifier of the option within the chosen `choice` to
                  book — this is the actual offering being scheduled (e.g.
                  a specific appointment type). Must be one of the options
                  the choice exposes.
                example: 5f1a83b9d52d5c2c8b8b4568
              item_configuration:
                type: object
                title: CreateOrderItemPackageItemConfiguration
                description: |
                  Per-item scheduling configuration: time, duration, room,
                  practitioners, areas, etc. Use this in preference to the
                  top-level scheduling fields (which remain for backward
                  compatibility but will be removed in a future major
                  version).
                additionalProperties: true
                properties:
                  time:
                    type: string
                    description: Time of day for the booking in `HH:mm` format.
                    example: '14:30'
                  duration:
                    type: integer
                    minimum: 1
                    description: Duration in minutes.
                  room_id:
                    type: string
                    nullable: true
                    description: The room to host this booking in, if any.
                  practitioner_ids:
                    type: array
                    nullable: true
                    description: Practitioners assigned to this booking.
                    items:
                      type: string
                  area_ids:
                    type: array
                    nullable: true
                    description: Areas occupied by this booking.
                    items:
                      type: string
                  session_id:
                    type: string
                    description: |
                      Session this item should join, if booking against a
                      group session.
              guest_ids:
                type: array
                items:
                  type: string
                description: |
                  The guests this package item is for. Each ID must belong
                  to a `Guest` already attached to the order.
              time:
                type: string
                description: |
                  Deprecated — use `item_configuration.time`. Time of day
                  for the booking in `HH:mm` format.
                example: '14:30'
                deprecated: true
              duration:
                type: integer
                description: |
                  Deprecated — use `item_configuration.duration`. Duration
                  in minutes.
                example: 60
                deprecated: true
              room_id:
                type: string
                nullable: true
                description: |
                  Deprecated — use `item_configuration.room_id`.
                example: 5f1a83b9d52d5c2c8b8b4570
                deprecated: true
              practitioner_ids:
                type: array
                items:
                  type: string
                nullable: true
                description: |
                  Deprecated — use
                  `item_configuration.practitioner_ids`.
                deprecated: true
              area_ids:
                type: array
                items:
                  type: string
                nullable: true
                description: |
                  Deprecated — use `item_configuration.area_ids`.
                deprecated: true
            required:
              - choice_id
              - option_id
    OrderLeadBooker:
      required: true
      content:
        application/json:
          schema:
            title: OrderLeadBooker
            type: object
            additionalProperties: false
            properties:
              first_name:
                type: string
                description: |
                  First name of the lead booker. Copied onto the order's
                  lead-booker `Guest` so the operator-facing guest list and
                  the order header stay aligned.
                example: Jane
              last_name:
                type: string
                description: Last name of the lead booker.
                example: Doe
              email:
                type: string
                format: email
                nullable: true
                description: Lead booker's email address.
              phone:
                type: string
                nullable: true
                description: |
                  Lead booker's phone number, validated against the site's
                  country code and stored in E.164 format.
                example: '+447700900123'
              tax_address_id:
                type: string
                nullable: true
                description: |
                  ID of one of the customer's existing addresses to copy
                  into the order's tax address. Useful for B2B sales where
                  the invoice needs to carry a specific billing address.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              legal_name:
                type: string
                nullable: true
                description: |
                  The legal entity name to use on tax documents — typically
                  a company name distinct from the lead booker's personal
                  name.
                example: Acme Hospitality Ltd
              tax_id:
                type: string
                nullable: true
                description: |
                  The tax identifier (VAT number, ABN, etc.) to record on
                  the order for downstream invoicing.
                example: GB123456789
              tax_id_type:
                type: string
                nullable: true
                enum:
                  - tax_number
                  - passport
                  - other
                description: |
                  The kind of tax identifier supplied — only meaningful
                  when `tax_id` is also provided.
    OrderOverpaymentToVoucher:
      required: true
      content:
        application/json:
          schema:
            title: OrderOverpaymentToVoucher
            type: object
            additionalProperties: false
            properties:
              voucher_type_id:
                type: string
                description: |
                  The `VoucherType` to issue the new voucher under. Must
                  belong to the order's site. The voucher inherits the
                  type's expiry, terms and presentation defaults.
                example: 5f1a83b9d52d5c2c8b8b4567
              notes:
                type: string
                nullable: true
                description: |
                  Free-form notes recorded against the new voucher. Plain
                  text only; HTML markup is rejected.
                example: Issued from order overpayment after partial refund.
            required:
              - voucher_type_id
    CreateOrderPaymentRefund:
      required: true
      content:
        application/json:
          schema:
            title: CreateOrderPaymentRefund
            type: object
            additionalProperties: false
            properties:
              amount:
                type: integer
                description: |
                  The amount to refund, expressed in the lowest denomination
                  of the order's currency (pennies for `GBP`, cents for
                  `USD`, etc.). Must not exceed the payment's
                  `refundable_amount`. The processor records a
                  `RefundLimitExceededException` on the order if it does;
                  the request is rejected with a `400`.
                example: 2500
              notes:
                type: string
                nullable: true
                description: |
                  Free-form notes recorded against the refund — for example
                  the reason or the operator who authorised it. Plain text
                  only; HTML markup is rejected.
                example: Refunded after guest complained about treatment.
              allocations:
                type: array
                description: |
                  For settled orders, an optional breakdown of which line
                  items the refund should be allocated against. Each entry
                  names a refundable line (`OrderRefundableItem.id`) and
                  the amount of the refund that should be attributed to
                  it. When omitted on a settled order, the refund is
                  allocated proportionally across the order's items.
                items:
                  type: object
                  title: OrderRefundAllocation
                  additionalProperties: false
                  properties:
                    item_id:
                      type: string
                      description: |
                        The refundable line to attribute this portion to.
                        Use `OrderRefundableItem.id`: a basket item
                        object-id for items, or the fixed keys `tip` /
                        `good_will` for those synthetic centres. Tip
                        refunds are keyed as `tip` (not a tip object-id).
                      example: tip
                    amount:
                      type: integer
                      description: |
                        The refund amount attributed to this item, in the
                        lowest denomination of the order's currency.
                  required:
                    - item_id
                    - amount
              processor:
                type: string
                description: |
                  For `pms_folio` and `external_voucher` payments, optionally
                  override the processor used to record the refund. Defaults
                  to the payment's original processor; passing `manual` lets
                  the operator record the refund without round-tripping the
                  external system. Ignored for other processor types.
                enum:
                  - manual
                  - pms_folio
                  - external_voucher
            required:
              - amount
    ReserveOrder:
      required: false
      content:
        application/json:
          schema:
            title: ReserveOrder
            type: object
            additionalProperties: false
            properties:
              reserve_mins:
                type: integer
                minimum: 1
                description: |
                  How long the underlying resources should be reserved for,
                  in minutes. Must be greater than zero. If omitted, the
                  site's default hold time is used. Reservations are
                  cooperative — they prevent another caller from booking
                  the same slot while the order is being finalised, but
                  expire automatically once the window elapses.
                example: 15
    SubmitOrder:
      required: false
      content:
        application/json:
          schema:
            title: SubmitOrder
            type: object
            additionalProperties: false
            properties:
              skip_availability_checks:
                type: boolean
                default: false
                description: |
                  When `true`, bypasses the second-pass availability
                  recheck normally run at submission time. Only takes
                  effect for users that hold the
                  `RESERVATIONS_OVERRIDE_RULES` permission — operators
                  without it have the flag silently ignored. Useful when
                  an operator has manually confirmed availability outside
                  the system and wants to push a borderline booking
                  through.
    CreateOrderVoucher:
      required: true
      content:
        application/json:
          schema:
            title: CreateOrderVoucher
            type: object
            additionalProperties: false
            properties:
              code:
                type: string
                description: |
                  The voucher code to redeem against this order. Must
                  reference a valid, unredeemed `VoucherCode` on the
                  order's site. On success, the voucher is recorded as a
                  payment against the order and its remaining balance is
                  decremented.
                example: GIFT-ABC123
            required:
              - code
    UpdatePractitionerRotaForDate:
      description: |
        Body for overriding a practitioner's working windows for a single
        date. The server reconciles the submitted `availability_rules`
        against the practitioner's regular rota and existing custom
        availability rules:

        - If the submitted rules match the rota's rules for the date,
          no custom rules are created — the rota is left to provide
          availability. Note: `room_id` in the request is ignored in
          this case, as there is no custom rule to persist it to.
        - If the submitted rules differ, the server clears any custom
          rules covering the date and creates one custom rule per
          submitted window (with `is_available: true`), preserving
          `room_id` if provided.
        - If `availability_rules` is omitted or empty, the server
          records a single all-day `is_available: false` custom rule,
          blocking bookings for the date.

        Any pre-existing custom rules that overlap the date but extend
        beyond it are trimmed or split to leave only the date untouched.

        Requires the `ROTAS_MANAGE` permission on the practitioner's
        first site.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionerRotaForDate
            type: object
            additionalProperties: false
            required:
              - date
            properties:
              date:
                type: string
                format: date
                description: The ISO 8601 date (`YYYY-MM-DD`) to override, interpreted in the practitioner's timezone.
                example: '2026-06-01'
              availability_rules:
                type: array
                description: |
                  The working windows to apply for the date. Each rule
                  defines a start and end time. Submitting an empty array
                  (or omitting the key) blocks the practitioner for the
                  entire date.
                items:
                  title: UpdatePractitionerRotaForDateRule
                  type: object
                  additionalProperties: false
                  required:
                    - time_from
                    - time_to
                  properties:
                    time_from:
                      type: string
                      description: |
                        Start time of the window in `HH:MM` 24-hour
                        format. Must be strictly less than `time_to`.
                      example: '09:00'
                    time_to:
                      type: string
                      description: End time of the window in `HH:MM` 24-hour format. Must be strictly greater than `time_from`.
                      example: '17:00'
                    is_available:
                      type: boolean
                      description: |
                        Only `true` (the default) is currently accepted —
                        blocked windows are expressed by omitting the rule,
                        not by sending `is_available: false`. Sent
                        explicitly only by older callers; new integrations
                        should leave it out.
                      enum:
                        - true
                    room_id:
                      type: string
                      format: object-id
                      nullable: true
                      description: |
                        The room the practitioner is assigned to during
                        this window. `null` (or omitted) means the
                        practitioner is not linked to a specific room for
                        this window. Only used when the submitted rules
                        differ from the rota's rules for the date; ignored
                        if the rules match the rota.
                    offerings:
                      type: array
                      description: |
                        The offerings the practitioner is assigned to
                        during this window. An empty array (or omitted)
                        means the practitioner is not linked to specific
                        offerings for this window. Only used when the
                        submitted rules differ from the rota's rules for
                        the date; ignored if the rules match the rota.
                      items:
                        $ref: '#/components/schemas/OfferingIdentifier'
    UpdatePractitionersOrder:
      description: |
        Body for reordering the practitioners for a site in one request.
        The order of `practitioner_ids` determines each practitioner's
        `order` field (first ID = `order: 0`, second = `order: 1`, and so
        on). IDs not listed are unaffected. Requires the `SETTINGS_MANAGE`
        permission on the target site.
      required: true
      content:
        application/json:
          schema:
            title: UpdatePractitionersOrder
            type: object
            additionalProperties: false
            required:
              - site_id
              - practitioner_ids
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the site whose practitioners are being reordered.
                  All `practitioner_ids` must belong to this site.
                example: 6f1234567890abcdef123456
              practitioner_ids:
                type: array
                description: |
                  Practitioner IDs in the desired display order. Index in
                  the array becomes the practitioner's `order` field.
                items:
                  type: string
                  format: object-id
                minItems: 1
    UpdateVoucherTypesOrder:
      description: |
        Body for reordering the voucher types for a site in one request.
        The order of `voucher_type_ids` determines each voucher type's
        `order` field (first ID → `order: 0`, second → `order: 1`, etc.).
        IDs not listed are unaffected.

        Requires the `SETTINGS_MANAGE` permission on the target site.
      required: true
      content:
        application/json:
          schema:
            title: UpdateVoucherTypesOrder
            type: object
            additionalProperties: false
            required:
              - site_id
              - voucher_type_ids
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  ID of the site whose voucher types are being reordered.
                  All `voucher_type_ids` must belong to this site.
                example: 6f1234567890abcdef123456
              voucher_type_ids:
                type: array
                description: |
                  Voucher type IDs in the desired display order. The index
                  of each ID in the array becomes that voucher type's
                  `order` field.
                items:
                  type: string
                  format: object-id
                minItems: 1
    CopyEquipment:
      description: |
        Body for copying an `Equipment` item. Every field is optional;
        fields omitted from the body are inherited from the source equipment.
        Provide `site_id` to clone the equipment into a different site
        (subject to the caller having `SETTINGS_MANAGE` there).
      required: false
      content:
        application/json:
          schema:
            title: CopyEquipment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the new copy. Defaults to the source's name — usually you'll want to override this so the two entries are distinguishable.
                example: Massage Table (Site B)
              description:
                type: string
                description: Override the long-form description on the copy. Defaults to the source's description.
                example: Heated massage table for deep-tissue work.
              quantity:
                type: number
                description: Override the unit count available at the site. Must be greater than zero. Defaults to the source's value.
                example: 4
              site_id:
                type: string
                format: uuid
                description: |
                  Override the site the copy belongs to. Defaults to the
                  source's site. The calling user must belong to the target
                  site.
                example: 00000000-0000-0000-0000-111111111111
    UpdateIntakeFormQuestion:
      description: |
        Body for updating an existing `IntakeFormQuestion`. `type` is
        required (and triggers conditional validation on
        `multiple_choice_answers` etc.); every other field is optional and
        only the fields supplied are updated.
      required: true
      content:
        application/json:
          schema:
            title: UpdateIntakeFormQuestion
            type: object
            additionalProperties: false
            allOf:
              - $ref: '#/components/schemas/IntakeFormQuestionWritableFields'
              - type: object
                additionalProperties: false
                required:
                  - type
    OfferingDayUnavailability:
      description: |
        Body identifying the offering and the calendar day to mark
        unavailable. The day boundary is interpreted in the offering's
        timezone.
      required: true
      content:
        application/json:
          schema:
            title: OfferingDayUnavailability
            type: object
            additionalProperties: false
            properties:
              date:
                type: string
                format: date
                description: |
                  ISO 8601 calendar date to mark unavailable, in the
                  offering's timezone.
                example: '2026-12-25'
              offering_type:
                type: string
                description: The offering type the `offering_id` belongs to.
                enum:
                  - appointment
                  - area_booking
                  - package
                  - session
              offering_id:
                type: string
                description: ID of the offering to update.
                example: 5dcb47800000000000000019
            required:
              - date
              - offering_type
              - offering_id
    CopyOrganisationLabel:
      description: |
        Body for copying an organisation `Label`. `name` and `site_ids` are
        required so the copy is distinct from the source.
      required: true
      content:
        application/json:
          schema:
            title: CopyOrganisationLabel
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Display name for the new copy. Plain text only (any HTML
                  is rejected); maximum 40 characters.
                maxLength: 40
                example: VIP Guests (West Sites)
              color:
                type: string
                nullable: true
                description: |
                  Six-digit hex colour with a leading `#`. Defaults to the
                  source's colour when omitted.
                pattern: ^#[0-9a-fA-F]{6}$
                example: '#3366cc'
              site_ids:
                type: array
                description: |
                  UUIDs of the sites the copy is visible at. Every ID must
                  belong to the organisation in the path. Replaces (does
                  not extend) the source's site list.
                items:
                  type: string
                  format: uuid
                  example: 00000000-0000-0000-0000-111111111111
            required:
              - name
              - site_ids
    UpdateSalesChannelsOrder:
      description: |
        Body for updating the organisation-wide sales channel order. Pass
        every channel ID you want positioned in the desired sequence; IDs
        not included are appended to the tail in their existing relative
        order.
      required: true
      content:
        application/json:
          schema:
            title: UpdateSalesChannelsOrder
            type: object
            additionalProperties: false
            properties:
              organisation_id:
                type: string
                format: uuid
                description: |
                  UUID of the organisation whose channels are being
                  reordered. Must match the `organisationId` in the path.
                example: 00000000-0000-0000-0000-000000000000
              sales_channel_ids:
                type: array
                description: |
                  The desired display sequence of `SalesChannel` IDs.
                items:
                  type: string
                  format: object-id
                  example: 5dcb47800000000000000001
            required:
              - organisation_id
              - sales_channel_ids
    ReorderPackageItemChoices:
      description: |
        Body for reordering the item-choice groups on a `Package`. Provide
        the desired sequence of group IDs in `order`.
      required: true
      content:
        application/json:
          schema:
            title: ReorderPackageItemChoices
            type: object
            additionalProperties: false
            properties:
              order:
                type: array
                description: |
                  The desired sequence of item-choice group IDs. IDs not
                  listed are appended to the tail in their existing relative
                  order. Unknown IDs are silently ignored.
                items:
                  type: string
                  description: An `item_choices[].id` on the package.
                  example: 5dcb47800000000000000001
            required:
              - order
    CopyRoomReservationType:
      description: |
        Body for copying a `TableReservationType` via the
        `room-reservation-types` URL alias. Every field is optional; fields
        omitted from the body are inherited from the source reservation
        type. Pass `site_id` to clone the reservation type into a
        different site (subject to the caller belonging to that site).
      required: false
      content:
        application/json:
          schema:
            title: CopyRoomReservationType
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: Display name for the new copy. Defaults to the source's name — usually you'll want to override this so the two entries are distinguishable.
                example: Cabana — VIP Copy
              description:
                type: string
                nullable: true
                description: Override the long-form description. Defaults to the source's value.
                example: Enjoy a relaxing meal in our main restaurant.
              image_id:
                type: string
                nullable: true
                description: ID of an uploaded `Media` to use as the cover image. Defaults to the source's image.
                example: 5f1234567890abcdef123456
              product_code:
                type: string
                nullable: true
                description: Override the POS/PMS product code. Defaults to the source's value.
                example: DIN
              external_id:
                type: string
                nullable: true
                description: Override the external identifier. Defaults to the source's value.
                example: resdiary:12345
              provider:
                type: string
                description: |
                  Integration provider that backs the reservation type.
                enum:
                  - resdiary
              integration_config_id:
                type: string
                nullable: true
                format: object-id
                description: |
                  ID of an existing `IntegrationConfig` on the target site
                  to attach the copy to. Defaults to the source's value.
              site_id:
                type: string
                format: uuid
                description: |
                  Override the site the copy belongs to. Defaults to the
                  source's site. The calling user must belong to the target
                  site.
    CreateCheckIn:
      content:
        application/json:
          schema:
            title: CreateCheckIn
            type: object
            additionalProperties: false
            properties:
              customer_id:
                type: string
                description: The customer ID associated with this check-in
                example: 000000-000000-000000-000000
              membership_id:
                type: string
                description: The membership ID associated with this check-in
                example: 000000-000000-000000-000000
              site_id:
                type: string
                description: The site ID where this check-in happened
                example: 000000-000000-000000-000000
              method_id:
                type: string
                nullable: true
                description: |
                  Identifier of the method that produced the check-in.
                  Use one of the generic string codes (`scanned`,
                  `check_in_button`) for human-driven check-ins, or the
                  ID of an integrated resource such as a Gantner device
                  for hardware-driven check-ins. When passing a resource
                  ID, also set `method_type` accordingly.
                example: scanned
              method_type:
                type: string
                nullable: true
                description: |
                  The type of method used to create this check-in. Omit this field for a generic method, or set to `gantner` when the method is an allowed resource such as a Gantner Device.
                enum:
                  - gantner
            required:
              - customer_id
              - site_id
    CreateCustomerAddress:
      content:
        application/json:
          schema:
            title: CreateCustomerAddress
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Short label the customer uses to identify the address —
                  shown in address pickers at checkout. Typical values are
                  `Home`, `Work` or a contact name.
                example: Home
              address_line_1:
                type: string
                description: |
                  First line of the postal address — usually the street
                  number and street name. Required because postal carriers
                  cannot deliver without it.
                example: 123 Fake Street
              address_line_2:
                type: string
                description: |
                  Optional second line of the postal address, used for
                  suite/apartment numbers or building names that don't fit
                  on `address_line_1`.
                example: Some building
                nullable: true
              city:
                type: string
                description: |
                  City or town the address sits in. Optional because some
                  rural addresses don't use a city line; when omitted the
                  postcode is used for delivery routing.
                example: London
                nullable: true
              county:
                type: string
                description: |
                  County, state or province. Optional in regions where the
                  postcode alone uniquely identifies a delivery area.
                example: London
                nullable: true
              country:
                type: string
                description: |
                  Country the address is in. Free text rather than an ISO
                  code so the customer can match the wording used on their
                  shipping documents.
                example: United Kingdom
                nullable: true
              postcode:
                type: string
                description: |
                  Postal/ZIP code for the address. Optional because some
                  countries don't use postcodes, but strongly recommended
                  for delivery routing where they exist.
                example: E14 1AA
                nullable: true
            required:
              - name
              - address_line_1
    UpdateCustomerAddress:
      content:
        application/json:
          schema:
            title: UpdateCustomerAddress
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Replacement label the customer uses to identify the
                  address. Shown in address pickers at checkout.
                example: Home
              address_line_1:
                type: string
                description: |
                  Replacement first line of the postal address — usually
                  the street number and street name.
                example: 123 Fake Street
              address_line_2:
                type: string
                description: |
                  Replacement second line of the postal address, used for
                  suite/apartment numbers or building names. Pass `null`
                  to clear.
                example: Some building
                nullable: true
              city:
                type: string
                description: |
                  Replacement city or town for the address. Pass `null`
                  to clear.
                example: London
                nullable: true
              county:
                type: string
                description: |
                  Replacement county, state or province. Pass `null` to
                  clear.
                example: London
                nullable: true
              country:
                type: string
                description: |
                  Replacement country for the address. Free text rather
                  than an ISO code. Pass `null` to clear.
                example: United Kingdom
                nullable: true
              postcode:
                type: string
                description: |
                  Replacement postal/ZIP code for the address. Pass `null`
                  to clear.
                example: E14 1AA
                nullable: true
    AssociateCustomerBarcode:
      content:
        application/json:
          schema:
            title: AssociateCustomerBarcode
            type: object
            additionalProperties: false
            properties:
              data:
                title: AssociateCustomerBarcodeData
                type: object
                additionalProperties: false
                properties:
                  barcode:
                    type: string
                    description: The payload of the barcode to associate
                  expires_at:
                    type: string
                    format: date-time
                    description: The datetime which the barcode will expire
                    example: '2021-03-10T00:00:00+00:00'
                    nullable: true
            required:
              - data
    IssueCustomerCredit:
      description: Details of the credit to issue to the customer
      content:
        application/json:
          schema:
            title: IssueCustomerCredit
            type: object
            additionalProperties: false
            properties:
              coupon_id:
                type: string
                format: uuid
                description: |
                  The `Coupon` template that defines what the credit
                  entitles the customer to spend (offering, monetary
                  value, redemption rules). Every credit is issued from a
                  coupon — there is no free-form credit grant.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              customer_id:
                type: string
                format: uuid
                description: |
                  The `Customer` the credit is issued to. Credits are
                  scoped to a single customer and cannot be transferred
                  between customers later.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              membership_id:
                type: string
                format: uuid
                description: |
                  The `Membership` the credit relates to, if the credit
                  is being issued as part of a membership benefit (e.g.
                  a monthly recurring complimentary treatment). Omit for
                  one-off credits unrelated to a membership.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              expiry_date:
                type: string
                format: date-time
                description: The datetime which the credit will expire
                example: '2021-03-10T00:00:00.000Z'
              revenue:
                type: integer
                description: The amount of revenue that should be allocated when this credit is redeemed, in the smallest unit of currency.
                example: 2495
            required:
              - coupon_id
              - customer_id
    AttachDetachCustomerLabels:
      content:
        application/json:
          schema:
            title: AttachDetachCustomerLabels
            type: object
            additionalProperties: false
            properties:
              labels:
                type: array
                description: An array of label IDs to attach to (or detach from) the customer.
                items:
                  type: string
                  format: uuid
                  description: The ID of the label to attach/detach
                  example: 000000-000000-000000-000000
            required:
              - labels
    CreateCustomerNote:
      content:
        application/json:
          schema:
            title: CreateCustomerNote
            type: object
            additionalProperties: false
            properties:
              note:
                type: string
                description: |
                  Body of the note in plain text. Notes are operator-only
                  context (not surfaced to guests) and are displayed in
                  reverse-chronological order on the customer record.
                example: VIP guest — please welcome by name at reception.
            required:
              - note
    UpdateCustomerNote:
      content:
        application/json:
          schema:
            title: UpdateCustomerNote
            type: object
            additionalProperties: false
            properties:
              note:
                type: string
                description: |
                  Replacement body for the note in plain text. The
                  note's author and timestamps are not updated.
                example: VIP guest — please welcome by name at reception.
    CreateLabel:
      content:
        application/json:
          schema:
            title: CreateLabel
            type: object
            additionalProperties: false
            properties:
              value:
                type: string
                description: |
                  Display text shown on the label badge against a
                  customer. Operator-facing only — there is no
                  guest-visible surface for labels. Limited to 20
                  characters so the badge fits in customer-list rows.
                maxLength: 20
                example: VIP
              colour:
                type: string
                description: A hex colour code excluding the preceding \# which this label will be rendered as.
                maxLength: 6
                example: ff6634
              organisation_id:
                type: string
                format: uuid
                description: The organisation which this label belongs to
                example: 000000-000000-000000-000000
            required:
              - value
              - colour
    UpdateLabel:
      content:
        application/json:
          schema:
            title: UpdateLabel
            type: object
            additionalProperties: false
            properties:
              value:
                type: string
                description: |
                  Display text shown on the label badge against a
                  customer. Operator-facing only — there is no
                  guest-visible surface for labels. Limited to 20
                  characters so the badge fits in customer-list rows.
                maxLength: 20
                example: VIP
              colour:
                type: string
                description: A hex colour code excluding the preceding \# which this label will be rendered as.
                maxLength: 6
                example: ff6634
    RefundMembershipCharge:
      description: Details of the refund to issue against the membership charge.
      content:
        application/json:
          schema:
            title: RefundMembershipCharge
            type: object
            additionalProperties: false
            properties:
              amount:
                type: integer
                description: The amount to refund from this charge as an integer of the smallest unit (e.g. pence)
                example: 1000
              note:
                type: string
                description: A custom description of why this refund was made
                example: Customer forgot to cancel last week
            required:
              - amount
    UpdateMembershipRateLocaleStrings:
      description: Update locale strings for a MembershipRate
      required: true
      content:
        application/json:
          schema:
            title: UpdateMembershipRateLocaleStrings
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                nullable: true
                description: The localised name for this membership rate in the given locale.
                example: Monthly Spa Membership
    UpdateMembershipRate:
      description: Details to update the membership rate with.
      content:
        application/json:
          schema:
            title: UpdateMembershipRate
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: |
                  Operator-facing label for the rate. Shown alongside the
                  membership type when staff issue or amend memberships.
                  Common values include `Standard rate`, `Concession` and
                  `Founder`.
                example: Standard rate
              price:
                type: integer
                description: The price of the rate as an integer of the smallest unit (eg pence).
                example: 5000
              currency:
                type: string
                description: The currency of the price, uppercase, in the ISO4217 format
                example: GBP
              joining_fee:
                type: integer
                description: The price of the joining fee as an integer of the smallest unit (eg pence).
                example: 1000
              private:
                type: boolean
                description: Whether this rate is private
                example: true
              billing_frequency:
                type: string
                description: |
                  The frequency that this membership is billed.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                example: P1M
              default_duration:
                type: string
                description: |
                  The default duration of the membership. This is used when a customer signs themselves up
                  for a membership. The duration is specified as an ISO8601 duration string.
                example: P1Y
              notice_period:
                type: string
                nullable: true
                enum:
                  - P7D
                  - P14D
                  - P1M
                  - P3M
                  - P6M
                  - P1Y
                  - null
                description: |
                  How much notice a customer must give to cancel a membership on this rate.
                  The duration is specified as an ISO8601 duration string. See https://en.wikipedia.org/wiki/ISO_8601#Durations
                  When null, no notice is required.
                example: P1M
    AddManualPayment:
      description: The manual payment details to record against the membership.
      content:
        application/json:
          schema:
            title: AddManualPayment
            type: object
            additionalProperties: false
            properties:
              processor_type_id:
                type: string
                description: |
                  The custom payment-processor type to attribute this
                  manual payment to (e.g. a cash, bank-transfer or
                  gift-card processor configured on the site). The
                  platform uses this to group the payment in revenue
                  reports without going through a real card processor.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
            required:
              - processor_type_id
    AddMembershipMember:
      description: Details of the customer to add to the membership.
      content:
        application/json:
          schema:
            title: AddMembershipMember
            type: object
            additionalProperties: false
            properties:
              customer_id:
                type: string
                format: uuid
                description: |
                  The `Customer` to add as a member of the membership.
                  The customer must belong to the same brand as the
                  membership; the platform rejects cross-brand additions
                  with `422 Unprocessable Entity`.
            required:
              - customer_id
    CreateSubscription:
      description: Details of the subscription to create.
      content:
        application/json:
          schema:
            title: CreateSubscription
            type: object
            additionalProperties: false
            properties:
              notification_type:
                type: string
                description: The type of notification to subscribe to
                enum:
                  - failed_payments
                  - expiring_soon
                  - new_signups
                  - revoked_mandate
              site_id:
                type: string
                format: uuid
                description: The site ID to subscribe to events for
            required:
              - notification_type
              - site_id
    CreateSignupToken:
      description: Details of the signup token to create.
      content:
        application/json:
          schema:
            title: CreateSignupToken
            type: object
            additionalProperties: false
            properties:
              membership_type_id:
                type: string
                description: The MembershipType this token allows signups as
                example: 000000-000000-000000-000000
              membership_rate_id:
                type: string
                description: |
                  The MembershipRate this token allows signups as. This must belong to the same
                  MembershipType as the one provided. If omitted, the default rate of the given type
                  will be used.
                example: 000000-000000-000000-000000
              start_date:
                type: string
                description: |
                  Optionally, you can specify the date which the membership should start.
                  This should not be specified if a `duration` is given.
                format: date
                example: '2021-02-21'
              end_date:
                type: string
                description: |
                  Optionally, you can specify the date which the membership should end.
                  This should not be specified if a `duration` is given.
                format: date
                example: '2022-02-21'
                nullable: true
              duration:
                type: string
                description: |
                  Optionally, you can specify the duration of the membership as an ISO8601 string. See
                  https://en.wikipedia.org/wiki/ISO_8601#Durations. This should not be specified if either
                  a `start_date` or `end_date` is given.
                example: P1M
              max_uses:
                type: integer
                nullable: true
                description: |
                  The maximum number of times this signup token can be used. If null, it can be used an
                  unlimited number of times. When the number of uses reaches the max_uses, it is soft-deleted.
                example: 1
              first_name:
                type: string
                description: The first name of the customer this token allows signups as.
                example: Dan
              last_name:
                type: string
                description: The last name of the customer this token allows signups as.
                example: Johnson
              email:
                type: string
                description: The email of the customer this token allows signups as.
                nullable: true
                example: dan.johnson@example.com
            required:
              - membership_type_id
    UpdateSignupToken:
      description: Details to update the signup token with.
      content:
        application/json:
          schema:
            title: UpdateSignupToken
            type: object
            additionalProperties: false
            properties:
              membership_type_id:
                type: string
                description: The MembershipType this token allows signups as
                example: 000000-000000-000000-000000
              membership_rate_id:
                type: string
                description: |
                  The MembershipRate this token allows signups as. This must belong to the same
                  MembershipType as the one provided. If omitted, the default rate of the given type
                  will be used.
                example: 000000-000000-000000-000000
              start_date:
                type: string
                description: Optionally, you can specify the date which the membership should start.
                format: date
                example: '2021-02-21'
              end_date:
                type: string
                description: Optionally, you can specify the date which the membership should end.
                format: date
                example: '2022-02-21'
                nullable: true
              duration:
                type: string
                description: |
                  Optionally, you can specify the duration of the membership as an ISO8601 string. See
                  https://en.wikipedia.org/wiki/ISO_8601#Durations
                example: P1M
              max_uses:
                type: integer
                nullable: true
                description: |
                  The maximum number of times this signup token can be used. If null, it can be used an
                  unlimited number of times.
                example: 1
              first_name:
                type: string
                description: The first name of the customer this token allows signups as.
                example: Dan
              last_name:
                type: string
                description: The last name of the customer this token allows signups as.
                example: Johnson
              email:
                type: string
                description: The email of the customer this token allows signups as.
                nullable: true
                example: dan.johnson@example.com
    UpdateMobilePassCustomisation:
      description: Details to update the mobile pass customisation with.
      content:
        application/json:
          schema:
            title: UpdateMobilePassCustomisation
            type: object
            additionalProperties: false
            properties:
              icon_id:
                type: string
                format: uuid
                description: |
                  `Media` to use as the icon on the mobile pass. Apple
                  Wallet renders this in notifications; aim for a small
                  square image. Must already be uploaded via the Media
                  API.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              logo_id:
                type: string
                format: uuid
                description: |
                  `Media` to use as the logo on the mobile pass. Shown
                  at the top of the pass next to the brand name.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              strip_id:
                type: string
                format: uuid
                description: The media id of the strip image
                example: 000000-000000-000000-000000
              background_colour:
                type: string
                description: |
                  Background hex colour for the pass, excluding the
                  leading `#`. Use the brand colour that contrasts well
                  with white text.
                example: 1a1a2e
              foreground_colour:
                type: string
                description: |
                  Foreground hex colour for the primary pass copy,
                  excluding the leading `#`. Pick a value with high
                  contrast against `background_colour`.
                example: ffffff
              label_colour:
                type: string
                description: |
                  Hex colour for the small field labels on the pass,
                  excluding the leading `#`. Defaults to a slightly
                  dimmer shade than `foreground_colour`.
                example: cccccc
              enabled:
                type: boolean
                description: Whether or not to enable mobile passes for this site
            required:
              - icon_id
    CreateInventoryAdjustment:
      required: true
      content:
        application/json:
          schema:
            title: CreateInventoryAdjustment
            type: object
            additionalProperties: false
            required:
              - product_id
              - quantity
            properties:
              product_id:
                type: string
                format: uuid
                description: |
                  `Product` whose stock level is being adjusted. The
                  product must be configured on the same brand as the
                  caller; cross-brand adjustments are rejected with
                  `422`.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              quantity:
                type: integer
                description: |
                  Signed change to the on-hand stock count. Positive
                  values increase stock (e.g. a receipt or correction
                  upwards); negative values decrease it (e.g. waste,
                  transfers out).
                example: -3
              reason_code:
                type: string
                description: |
                  Machine-readable reason for the adjustment, used for
                  reporting. Common values are `waste`, `transfer`,
                  `correction` and `theft`. Free text — define your own
                  codes as needed.
                example: waste
              reason_description:
                type: string
                description: |
                  Optional human-readable explanation that staff and
                  auditors see alongside the adjustment. Use this to add
                  detail that the `reason_code` doesn't capture.
                example: Damaged in transit — three units written off.
              location_id:
                type: integer
                nullable: true
                description: |
                  `InventoryLocation` the stock is moving from. Optional
                  for sites that don't track per-location stock; required
                  when the product is location-aware.
                example: 12
              site_id:
                type: string
                format: uuid
                description: |
                  Site the adjustment is recorded against. Used for
                  site-level inventory reporting and to enforce the
                  caller's site permissions.
                example: 5dcb47800000000000000010
    CreateInventoryLocation:
      required: true
      content:
        application/json:
          schema:
            title: CreateInventoryLocationRequest
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: |
                  Site the new inventory location belongs to. Locations
                  are scoped to a single site so that stock counts and
                  adjustments stay isolated per site, even when sites
                  share the same product catalogue.
                example: 5dcb47800000000000000010
              name:
                type: string
                maxLength: 100
                description: A display name for the location.
                example: Treatment store
            required:
              - name
    UpdateInventoryLocation:
      required: true
      content:
        application/json:
          schema:
            title: UpdateInventoryLocation
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                maxLength: 100
                description: A display name for the location.
                example: Treatment store
    CreateInventoryProductSupplierLink:
      required: true
      content:
        application/json:
          schema:
            title: CreateInventoryProductSupplierLink
            type: object
            additionalProperties: false
            required:
              - supplier_id
            properties:
              supplier_id:
                type: string
                format: uuid
                description: |
                  `Supplier` to attach to the product. Suppliers belong to
                  the same inventory brand as the product; cross-brand
                  links are rejected with `422`. A product can be linked
                  to multiple suppliers, each with their own pricing.
                example: 5f8a1b2c-9d3e-4a5b-8c6d-7e8f9a0b1c2d
              supplier_product_id:
                type: string
                description: The supplier's ID of the product being ordered (e.g. their SKU).
                example: MRJ-45-100
              order_quantity:
                type: integer
                description: The default quantity of the product to order from this supplier.
                example: 10
              unit_price:
                type: integer
                description: The unit price of this item in the lowest denomination for the product's currency.
                example: 200
              currency:
                type: string
                description: The currency of the supplier product.
                example: gbp
    UpdateInventoryProductSupplierLink:
      required: true
      content:
        application/json:
          schema:
            title: UpdateInventoryProductSupplierLink
            type: object
            additionalProperties: false
            properties:
              order_quantity:
                type: integer
                description: The default quantity of the product to order from this supplier.
                example: 10
              supplier_product_id:
                type: string
                description: The supplier's ID of the product (e.g. their SKU).
                example: MRJ-45-100
              unit_price:
                type: integer
                description: The unit price of this item in the lowest denomination for the product's currency.
                example: 200
    UpdateSiteTaxInfo:
      required: true
      content:
        application/json:
          schema:
            title: UpdateSiteTaxInfo
            type: object
            additionalProperties: false
            required:
              - tax_id
              - address_line_1
              - city
              - country
              - postcode
            properties:
              tax_id:
                type: string
                description: The tax ID, ie the VAT number.
                example: GB 123 4567 89
              company_number:
                type: string
                nullable: true
                description: Company registration number, for example SIRET for French businesses
                example: '12345678901234'
              fr_naf_code:
                type: string
                maxLength: 6
                nullable: true
                description: NAF code for French businesses
                example: 56.10A
              address_line_1:
                type: string
                description: The first address line of the registered company.
                example: 71 Aldwych
              address_line_2:
                type: string
                nullable: true
                description: The second address line of the registered company.
                example: WeWork
              city:
                type: string
                description: The city of the registered company.
                example: London
              county:
                type: string
                nullable: true
                description: The county of the registered company.
                example: London
              country:
                type: string
                description: The country of the registered company.
                example: United Kingdom
              postcode:
                type: string
                description: The postcode of the registered company.
                example: WC2B 4HN
    CreateYieldRules:
      required: true
      content:
        application/json:
          schema:
            title: CreateYieldRules
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: The site the rules belong to.
              offerings:
                type: array
                minItems: 1
                maxItems: 1000
                description: |
                  The offerings to apply this rule to. One independent rule is
                  created for each, so editing one afterwards does not affect the
                  others. Repeating an offering creates a single rule for it.

                  Each offering must belong to `site_id` and have a standard price
                  for the adjustment to work from, and they must all share one
                  `offering_type` — a single rule cannot span types, because what a
                  rule may contain differs between them.

                  More than 200 offerings are created by a background job and
                  answered with `202`.
                items:
                  $ref: '#/components/schemas/YieldRuleOfferingIdentifier'
              weekdays:
                type: array
                minItems: 1
                items:
                  $ref: '#/components/schemas/weekday'
              time_from:
                type: string
                nullable: true
                description: |
                  24-hour `HH:MM`, in the site's local time. Send `null` for both this
                  and `time_to` for a rule that applies all day; one without the other
                  is rejected.
                example: '12:00'
              time_to:
                type: string
                nullable: true
                description: |
                  24-hour `HH:MM`, in the site's local time. Must differ from
                  `time_from`. An earlier value means the window runs past midnight
                  into the following day, and each selected weekday is the day its
                  window starts on — Monday with `22:30`–`00:30` runs Monday 22:30 to
                  Tuesday 00:30. Send `null` for both this and `time_from` for a rule
                  that applies all day.
                example: '21:00'
              triggers:
                $ref: '#/components/schemas/YieldRuleTriggers'
              adjustment:
                $ref: '#/components/schemas/YieldRuleAdjustment'
              rounding:
                $ref: '#/components/schemas/yieldRounding'
              reporting_tier:
                $ref: '#/components/schemas/yieldReportingTier'
              reduction_advance_interval:
                type: string
                description: |
                  How far ahead of a slot a rule that lowers the price may start
                  applying, as an ISO-8601 duration.

                  The window belongs to the offering rather than the rule: every rule
                  that lowers an offering's price shares the one window. Sending it
                  here sets it on all of the offerings the rule is being created for,
                  overwriting whatever each already had, so a value set from one
                  offering can be replaced by a rule created across many.

                  A rule that lowers a price cannot exist on an offering with no
                  window, so one must either be sent here or already be configured on
                  every offering listed. Rules that raise a price ignore the window
                  and need not send it.

                  Omit the key to leave each offering's window as it is. It cannot be
                  sent empty: a window is taken away from the offering itself, where
                  the check that no rule still depends on it lives.
                example: P2D
            required:
              - site_id
              - offerings
              - weekdays
              - time_from
              - time_to
              - triggers
              - adjustment
              - reporting_tier
    UpdateYieldRule:
      required: true
      content:
        application/json:
          schema:
            title: UpdateYieldRule
            type: object
            additionalProperties: false
            description: |
              Replaces the rule's definition in full. The offering it applies to is
              fixed at creation and cannot be changed, and rules created alongside
              this one are left untouched.

              Every field is required, since omitting one would silently keep its
              previous value. Send `rounding` as `null` for no rounding.

              `reduction_advance_interval` is not accepted here and is rejected if
              sent. When reductions may start belongs to the offering and is shared
              by every rule lowering its price, so only creating a rule may set it;
              changing it afterwards is done from the offering.
            properties:
              weekdays:
                type: array
                minItems: 1
                items:
                  $ref: '#/components/schemas/weekday'
              time_from:
                type: string
                nullable: true
                description: |
                  24-hour `HH:MM`, in the site's local time. Send `null` for both this
                  and `time_to` for a rule that applies all day; one without the other
                  is rejected.
                example: '12:00'
              time_to:
                type: string
                nullable: true
                description: |
                  24-hour `HH:MM`, in the site's local time. Must differ from
                  `time_from`. An earlier value means the window runs past midnight
                  into the following day, and each selected weekday is the day its
                  window starts on — Monday with `22:30`–`00:30` runs Monday 22:30 to
                  Tuesday 00:30. Send `null` for both this and `time_from` for a rule
                  that applies all day.
                example: '21:00'
              triggers:
                $ref: '#/components/schemas/YieldRuleTriggers'
              adjustment:
                $ref: '#/components/schemas/YieldRuleAdjustment'
              rounding:
                $ref: '#/components/schemas/yieldRounding'
              reporting_tier:
                $ref: '#/components/schemas/yieldReportingTier'
            required:
              - weekdays
              - time_from
              - time_to
              - triggers
              - adjustment
              - rounding
              - reporting_tier
    UpdateBarcodeExpiryDate:
      description: |
        The new expiry datetime for the associated barcode. Pass `null` to
        clear the expiry entirely; the barcode then remains valid until
        explicitly disassociated.
      required: true
      content:
        application/json:
          schema:
            title: UpdateBarcodeExpiryDate
            type: object
            additionalProperties: false
            properties:
              expires_at:
                type: string
                format: date-time
                description: |
                  The ISO-8601 datetime at which the barcode should stop
                  being accepted at kiosks, scanners and points-of-sale.
                  Must be in the future relative to the request time. Pass
                  `null` to remove any existing expiry.
                example: '2026-12-31T23:59:59+00:00'
                nullable: true
            required:
              - expires_at
    UpdateBarcodePaymentMethod:
      description: |
        The payment method to attach to the barcode. Pass `null` to detach
        the current method.
      required: true
      content:
        application/json:
          schema:
            title: UpdateBarcodePaymentMethod
            type: object
            additionalProperties: false
            properties:
              payment_method_id:
                type: string
                description: |
                  Identifier of a stored `PaymentMethod` belonging to the
                  same customer, used as the default charge target when
                  this barcode is presented at point-of-sale. For card
                  methods the card must still be valid on the underlying
                  processor profile. Pass `null` to detach the current
                  method.
                nullable: true
                example: 5e1e3f6c-2a44-4f6e-8c61-9c1f7d2e1c11
            required:
              - payment_method_id
    ChangeMembershipEndDate:
      description: |
        The new end date to apply to the membership.
      required: true
      content:
        application/json:
          schema:
            title: ChangeMembershipEndDate
            type: object
            additionalProperties: false
            properties:
              end_date:
                type: string
                format: date
                description: |
                  The new end date for the membership, in `YYYY-MM-DD`
                  format. Pass `null` to remove the end date entirely
                  (converting a fixed-term membership to open-ended).
                  Must be strictly after the membership's `start_date`.
                example: '2026-12-31'
                nullable: true
            required:
              - end_date
    UpdateMembershipStatus:
      description: |
        Options for the membership status refresh.
      required: false
      content:
        application/json:
          schema:
            title: UpdateMembershipStatus
            type: object
            additionalProperties: false
            properties:
              dry_run:
                type: boolean
                description: |
                  When `true`, computes the new `status` and
                  `attention_reason` but does **not** persist them. Use
                  this to surface the proposed change to an operator
                  before applying it. Defaults to `false`.
                example: false
            required: []
    UpdateMembershipTypeOrder:
      description: |
        The new display order for the caller's `MembershipType`s.
      required: true
      content:
        application/json:
          schema:
            title: UpdateMembershipTypeOrder
            type: object
            additionalProperties: false
            properties:
              membership_type_ids:
                type: array
                description: |
                  The `MembershipType` IDs in the new display order. The
                  first ID becomes order `0`, the second `1`, and so on.
                  IDs not included in this array retain their existing
                  `order` value.
                items:
                  type: string
                  format: uuid
                example:
                  - 9c4d6c4e-3a5a-4f6e-9d6b-1f7e8a9c0b1d
                  - 1b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e
            required:
              - membership_type_ids
    CreateCustomerSegment:
      content:
        application/json:
          schema:
            title: CreateCustomerSegment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: The display name of the segment.
                maxLength: 255
                example: Premium Members
              site_id:
                type: string
                format: uuid
                description: The ID of the site this segment belongs to.
              filters:
                type: object
                title: CreateCustomerSegmentFilters
                description: Optional filters that define automatic membership criteria for the segment.
                nullable: true
                additionalProperties: false
                properties:
                  all_customers:
                    type: boolean
                    description: When `true`, all customers in the site are included in the segment regardless of other filters.
                  label_ids:
                    type: array
                    description: Include customers that have all of the given label IDs.
                    nullable: true
                    minItems: 1
                    items:
                      type: string
                      format: uuid
                  membership_type_ids:
                    description: Include customers that hold a membership matching one of the given IDs. Use `true` to include customers with any active membership.
                    oneOf:
                      - type: array
                        minItems: 1
                        items:
                          type: string
                          format: uuid
                      - type: boolean
                        enum:
                          - true
            required:
              - name
              - site_id
    UpdateCustomerSegment:
      content:
        application/json:
          schema:
            title: UpdateCustomerSegment
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: The display name of the segment.
                maxLength: 255
                example: Premium Members
              filters:
                type: object
                title: UpdateCustomerSegmentFilters
                description: Filters that define automatic membership criteria for the segment.
                nullable: true
                additionalProperties: false
                properties:
                  all_customers:
                    type: boolean
                    description: When `true`, all customers in the site are included in the segment regardless of other filters.
                  label_ids:
                    type: array
                    description: Include customers that have all of the given label IDs.
                    nullable: true
                    minItems: 1
                    items:
                      type: string
                      format: uuid
                  membership_type_ids:
                    description: Include customers that hold a membership matching one of the given IDs. Use `true` to include customers with any active membership.
                    oneOf:
                      - type: array
                        minItems: 1
                        items:
                          type: string
                          format: uuid
                      - type: boolean
                        enum:
                          - true
    AddCustomerSegmentMember:
      content:
        application/json:
          schema:
            title: AddCustomerSegmentMember
            type: object
            additionalProperties: false
            properties:
              customer_id:
                type: string
                format: uuid
                description: The ID of the customer to add to the segment.
            required:
              - customer_id
    UpdateCustomerSegmentMember:
      content:
        application/json:
          schema:
            title: UpdateCustomerSegmentMember
            type: object
            additionalProperties: false
            properties:
              subscribed:
                type: boolean
                description: |
                  Set to `true` to re-subscribe the customer to this segment's communications,
                  or `false` to unsubscribe them.
    CreateCampaign:
      content:
        application/json:
          schema:
            title: CreateCampaign
            type: object
            additionalProperties: false
            properties:
              site_id:
                type: string
                format: uuid
                description: The ID of the site this campaign belongs to.
              name:
                type: string
                description: The display name of the campaign.
                example: Summer Promotion 2024
              segment_id:
                type: string
                format: uuid
                description: The ID of the `CustomerSegment` to send this campaign to. Required when provided.
            required:
              - site_id
              - name
    UpdateCampaign:
      content:
        application/json:
          schema:
            title: UpdateCampaign
            type: object
            additionalProperties: false
            properties:
              name:
                type: string
                description: The display name of the campaign.
                example: Summer Promotion 2024
              segment_id:
                type: string
                format: uuid
                description: The ID of the `CustomerSegment` to send this campaign to. Pass `null` to remove the assigned segment.
                nullable: true
              scheduled_at:
                type: string
                format: date-time
                description: The datetime at which this campaign should be sent. Pass `null` to unschedule the campaign.
                nullable: true
    CreateCampaignContent:
      content:
        application/json:
          schema:
            title: CreateCampaignContent
            type: object
            additionalProperties: false
            properties:
              locale:
                type: string
                description: The BCP 47 locale code for this content variant.
                example: en-GB
              subject:
                type: string
                description: The email subject line for this content variant.
                example: Exclusive summer offer just for you
              content:
                type: string
                description: The email body content in markdown.
                example: Hi there! We have a special offer just for you.
            required:
              - locale
    UpdateCampaignContent:
      content:
        application/json:
          schema:
            title: UpdateCampaignContent
            type: object
            additionalProperties: false
            properties:
              subject:
                type: string
                description: The email subject line for this content variant.
                example: Exclusive summer offer just for you
              content:
                type: string
                description: The email body content in markdown.
                example: Hi there! We have a special offer just for you.
x-tagGroups:
  - name: Booking Flow
    tags:
      - Availability
      - OfferingAvailability
      - Baskets
      - Orders
      - Appointments
      - AreaBookings
      - SessionBookings
      - Visits
      - AppointmentEnquiries
      - CheckIns
      - IntakeForms
      - IntakeFormDeletionPolicy
      - Contraindications
      - VoucherCodes
      - VoucherPurchases
  - name: Customers
    tags:
      - Customers
      - CustomerNotes
      - CustomerLabels
      - CustomerMarketingPreferences
      - CustomerCredits
      - CustomerSegments
      - CustomerSegmentMembers
      - Campaigns
      - MarketingPreferences
      - Marketing
      - Imports
      - MyAccount
      - PaymentMethods
      - SignupTokens
  - name: Memberships
    tags:
      - Memberships
      - MembershipCharges
      - MembershipCreditRules
      - MembershipRates
      - MembershipTypes
      - Subscriptions
  - name: Offerings catalog
    tags:
      - Offerings
      - AppointmentTypes
      - AreaBookingTypes
      - CourseTypes
      - HotelRoomTypes
      - Packages
      - Products
      - SessionTypes
      - TableReservationTypes
      - VisitType
      - VoucherTypes
      - OfferingSets
      - YieldRules
  - name: Calendar & Scheduling
    tags:
      - Sessions
      - SessionRecurrenceGroups
      - SchedulingIssues
      - Practitioners
      - PractitionerRotas
      - PractitionerTags
      - BlockedTimes
      - BlockedTimePresets
      - CalendarEvents
      - CalendarNotes
      - CommissionPackages
  - name: Inventory
    tags:
      - InventoryProducts
      - InventoryBrands
      - InventoryCategories
      - InventoryLocations
      - InventoryOrders
      - InventoryAdjustments
      - StockAdjustments
      - StockTakes
      - StockOnHand
      - Suppliers
  - name: Payments & Vouchers
    tags:
      - Payments
      - Refunds
      - Vouchers
      - VoucherDeliveryOption
      - VoucherLedger
      - CouponCodes
      - Coupons
      - DiscountTypes
      - DiscountUsage
      - DepositLedger
      - DepositExposure
      - LedgerLines
      - LedgerLinePostings
      - Payouts
      - TerminalRequests
      - TerminalTokenisations
  - name: Sites & Organisation
    tags:
      - Sites
      - Brands
      - Organisations
      - Rooms
      - RoomTags
      - BookableAreas
      - Zones
      - Equipment
      - RevenueCentres
      - TaxConfigurations
      - Users
      - Permissions
      - Labels
      - MessageFragments
      - SmsFragments
      - Media
      - ExternalIdTypes
      - Frontend
      - Shop
      - Meta
      - Notifications
      - Onboarding
  - name: Kiosk
    tags:
      - KioskBufferTimes
      - KioskConfiguration
      - KioskDevices
      - KioskInstructions
      - EscPosConnectors
  - name: Reports
    tags:
      - Reports
      - OrganisationReports
      - RevenueByCentre
      - SmsUsage
      - YieldInsights
  - name: Integrations
    tags:
      - BookingEngine
      - ExitGratuity
      - Fiscalisation
      - IntegrationConfigs
      - IntegrationOutages
      - Overnights
      - PartnerConfigs
      - PMS
  - name: Partner integrations
    tags:
      - AdyenIntegration
      - AvvioIntegration
      - FiasRelay
      - Fiskaltrust
      - Fiskaly
      - ForSight
      - Gantner
      - Giftpro
      - Guestline
      - HConnectIntegration
      - Hotsoft
      - Mews
      - PacesetterIntegration
      - PremierCoreMappings
      - ResDiaryIntegration
      - SevenRoomsIntegration
      - TeiIntegration
      - TwilioProvisioning
  - name: Webhooks
    tags:
      - WebhookCalls
      - WebhookConfig
  - name: Admin & Internal
    tags:
      - Admin
      - AuditLogs
      - FeatureFlags
      - Internal
      - InternalOrders
      - SecurityPolicies
      - Sudo
