> ## Documentation Index
> Fetch the complete documentation index at: https://docs.way.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a booking

> Creates bookings for the cart's items in a single call. Card bookings are created in `processing` state before the charge and return the Stripe client secret to confirm; non-card methods and zero totals confirm synchronously. See the [booking integration guide](/guides/build-a-booking-integration) for the full flow.



## OpenAPI

````yaml post /v1/brands/{brandId}/book-bulk
openapi: 3.0.0
info:
  title: Way Partner API
  description: >-
    REST API for Way partners: list experiences, check availability, run
    checkout, and manage bookings.
  version: '1.0'
servers:
  - url: https://api.letsway.com
    description: Production.
  - url: https://api.staging.letsway.com
    description: Staging.
security: []
tags:
  - name: Listings
    description: 'Retrieve the listings a brand offers: experiences, events, and resources.'
  - name: Availability
    description: Dates, sessions, and price tiers for scheduling a booking.
  - name: Carts & Checkout
    description: >-
      Payment intents and booking creation. The cart ID is a client-generated
      UUID; there is no create-cart endpoint.
  - name: Bookings
    description: Retrieve, cancel, and reschedule bookings.
  - name: Experiences
    description: Experience details, settings, custom questions, reviews, and hosts.
  - name: Brand Configuration
    description: Brand settings, taxonomy, terms, and promotion code validation.
  - name: Waitlists
    description: Waitlists for sold-out sessions and invitation handling.
  - name: Integrations
    description: Configured integrations, analytics, and room-charge validation.
  - name: Organizations
    description: Organization-level access across brands.
paths:
  /v1/brands/{brandId}/book-bulk:
    post:
      tags:
        - Carts & Checkout
      summary: Create a booking
      description: >-
        Creates bookings for the cart's items in a single call. Card bookings
        are created in `processing` state before the charge and return the
        Stripe client secret to confirm; non-card methods and zero totals
        confirm synchronously. See the [booking integration
        guide](/guides/build-a-booking-integration) for the full flow.
      operationId: BookingPublicController_bookBulk
      parameters:
        - $ref: '#/components/parameters/brandIdPath_28'
        - $ref: '#/components/parameters/AuthorizationHeader'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkBookingRequest'
            example:
              cartId: 14e722e0-048b-4c7b-a70d-5e812b2b761e
              purchaser:
                firstName: Alice
                lastName: Rivera
                emailAddress: alice@example.com
                phoneNumber: '+15550100'
              data:
                - experienceId: c99f70ee-1c0e-4534-a31a-96d5d966cc4b
                  sessionTime: '2026-07-14T10:00:00'
                  sessionDuration: 60
                  mode: shared
                  participants:
                    - firstName: Alice
                      lastName: Rivera
                      priceTierName: Participant
              paymentMethod: credit-card
              siteLanguage: en
              deviceType: pc
      responses:
        '201':
          description: Booking details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentResultDto'
              example:
                data:
                  subjectId: 1ccd47b4-8784-43a0-86a5-fc733265f3c4
                  subjectType: cart
                  confirmationCode: 55xNJqU3Q
                  amount: 100
                  currency: USD
                  clientSecret: null
                  metadata: null
      security:
        - Brand-API-Key: []
        - Organization-API-Key: []
components:
  parameters:
    brandIdPath_28:
      name: brandId
      in: path
      schema:
        type: string
      required: true
      description: >-
        The brand's ID - must match the brand your API key identifies (or the
        Way-Brand-Id header when one is sent).
    AuthorizationHeader:
      name: Authorization
      in: header
      schema:
        type: string
      description: >-
        Optional bearer token used only by loyalty-authenticated flows (for
        example Hyatt members); not required for standard integrations.
      required: false
  schemas:
    BulkBookingRequest:
      type: object
      properties:
        data:
          type: array
          items:
            type: object
            properties:
              sessionTime:
                type: string
                description: >-
                  Start of the chosen session - copy the session's startDateTime
                  from the sessions endpoint. A local date-time in the
                  experience's timezone, with no UTC offset.
                example: '2026-07-14T10:00:00'
              sessionDuration:
                type: number
                description: >-
                  Length of the session in minutes - copy the chosen session's
                  duration from the sessions endpoint.
                example: 60
              participants:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                      description: >-
                        Optional participant identifier. Way generates its own
                        participant IDs at booking time, so this can be omitted
                        when creating a booking.
                    firstName:
                      type: string
                      description: Participant's first name.
                      example: Alice
                    lastName:
                      type: string
                      description: Participant's last name.
                      example: Rivera
                    emailAddress:
                      type: string
                      pattern: >-
                        ^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
                      nullable: true
                      description: >-
                        Participant's email address. Optional - guest
                        communication defaults to the purchaser's contact
                        details.
                      example: alice@example.com
                    phoneNumber:
                      type: string
                      nullable: true
                      description: >-
                        Participant's phone number, including country code.
                        Optional.
                      example: '+15550100'
                    priceTierName:
                      type: string
                      description: >-
                        Name of the session price tier this participant books -
                        must match one of the chosen session's priceTiers[].name
                        from the sessions endpoint.
                      example: Participant
                    customQuestionResponses:
                      type: array
                      items:
                        type: object
                        properties:
                          questionId:
                            type: string
                            description: >-
                              ID of the custom question being answered, from the
                              custom questions endpoint.
                            example: q-dietary-01
                          answer:
                            type: array
                            items:
                              type: object
                              properties:
                                value:
                                  oneOf:
                                    - type: string
                                    - type: boolean
                                  description: >-
                                    The answer value - the selected option's
                                    display value for select questions, free
                                    text for text questions, or a boolean for
                                    checkboxes.
                                  example: vegetarian
                                key:
                                  type: string
                                  nullable: true
                                  description: >-
                                    The selected option's key for select-type
                                    questions; null for free-text and checkbox
                                    answers. Select keys must match one of the
                                    question's defined options.
                                  example: hotel-lobby
                              required:
                                - value
                            description: >-
                              The answer as an array of value/key pairs.
                              Multi-select questions send one entry per selected
                              option; text and checkbox questions send a single
                              entry.
                        required:
                          - questionId
                          - answer
                      description: >-
                        Answers to participant-scoped custom questions for this
                        guest (e.g. dietary restrictions). Required questions
                        must be answered or the booking fails with 422.
                  required:
                    - firstName
                    - lastName
                    - priceTierName
                description: >-
                  One entry per guest, each referencing a price tier of the
                  chosen session. For resource collections the entries represent
                  the resource units booked, and the array length must equal
                  resourceQuantity.
              mode:
                type: string
                enum:
                  - private
                  - shared
                description: >-
                  How the session is booked: shared joins the guest alongside
                  other bookings on the same session; private books the session
                  exclusively. Use private when the chosen session is a private
                  session or the listing's bookingAvailabilityMode is private.
                example: shared
              couponCode:
                type: string
                nullable: true
                description: Coupon code to apply to this item's price.
                example: SUMMER10
              discountAmount:
                type: number
                nullable: true
                description: >-
                  Fixed-amount discount to apply to this item, in the brand's
                  currency.
                example: 10
              discountPercentage:
                type: number
                nullable: true
                description: Percentage discount to apply to this item.
                example: 15
              accessCode:
                type: string
                nullable: true
                description: >-
                  Access code that unlocks an access-restricted experience for
                  booking.
                example: VIP-2026
              notes:
                type: string
                nullable: true
                description: >-
                  Free-text note attached to the booking, such as a special
                  request from the guest.
                example: Guest requested a window seat.
              metadata:
                type: object
                additionalProperties: {}
                nullable: true
                description: >-
                  Arbitrary key-value pairs stored with the booking for your own
                  use.
              internalNotes:
                type: string
                nullable: true
                description: >-
                  Internal note stored on the booking for brand staff; not shown
                  to the guest.
                example: VIP guest - assign senior host.
              listingAddOns:
                default: []
                type: array
                items:
                  type: object
                  properties:
                    listingAddOnId:
                      type: string
                      format: uuid
                      description: >-
                        ID of the listing add-on being purchased, from the
                        listing detail.
                      example: b3f1a2c4-5d6e-4f7a-8b9c-0d1e2f3a4b5c
                    quantity:
                      type: number
                      minimum: 0
                      exclusiveMinimum: true
                      description: >-
                        Number of units of the add-on to purchase. Must be a
                        positive integer.
                      example: 2
                  required:
                    - listingAddOnId
                    - quantity
                description: >-
                  Add-ons purchased with this item, referencing the listing's
                  add-ons.
              appliedCreditCodes:
                type: array
                items:
                  type: object
                  properties:
                    code:
                      type: string
                      description: The credit code being redeemed.
                      example: GC-7F3K9QW2
                    appliedValue:
                      type: number
                      description: >-
                        Amount drawn from this credit code, in the brand's
                        currency.
                      example: 25
                    sequence:
                      type: number
                      description: >-
                        Order in which this code is applied when multiple credit
                        codes are redeemed; codes are applied in ascending
                        sequence.
                      example: 1
                  required:
                    - code
                    - appliedValue
                    - sequence
                nullable: true
                description: >-
                  Credit codes redeemed against this item. Each entry records
                  the code, the amount drawn from it, and the order in which
                  codes are applied.
              intendedConfirmationCode:
                type: string
                description: >-
                  Confirmation code to assign to the booking instead of a
                  Way-generated one. Omit to let Way generate the code.
                example: U7dSqlzCA
              waitlistEntryId:
                type: string
                format: uuid
                description: >-
                  ID of the guest's waitlist entry when this booking redeems a
                  waitlist offer.
                example: 8a1a2b3c-4d5e-4f6a-8b9c-1d2e3f4a5b6c
              experienceId:
                type: string
                description: >-
                  ID of the experience being booked - use the chosen session's
                  experienceId from the sessions endpoint. For resource
                  collections the listing-level experienceId is null, so the
                  session's value is the one to send.
                example: c99f70ee-1c0e-4534-a31a-96d5d966cc4b
              resourceGroupId:
                type: string
                description: >-
                  ID of the resource group being booked, from the listing
                  detail's resourceGroups[].id. Required for resource-group
                  collections; omit for time-based experiences.
                example: 4a7d1e9b-2c5f-4b3a-8e6d-1f9a5c3b7e28
              resourceQuantity:
                type: number
                description: >-
                  Number of resource units to book (e.g. 2 cabanas). Required
                  for resource-group collections and must equal
                  participants.length, otherwise the API returns 422. Omit for
                  time-based experiences.
                example: 2
              additionalCustomQuestionResponses:
                type: array
                items:
                  type: object
                  properties:
                    questionId:
                      type: string
                      description: >-
                        ID of the custom question being answered, from the
                        custom questions endpoint.
                      example: q-pickup-point
                    answer:
                      type: array
                      items:
                        type: object
                        properties:
                          value:
                            oneOf:
                              - type: string
                              - type: boolean
                            description: >-
                              The answer value - the selected option's display
                              value for select questions, free text for text
                              questions, or a boolean for checkboxes.
                            example: Hotel lobby
                          key:
                            type: string
                            nullable: true
                            description: >-
                              The selected option's key for select-type
                              questions; null for free-text and checkbox
                              answers.
                            example: hotel-lobby
                        required:
                          - value
                      description: >-
                        The answer as an array of value/key pairs. Multi-select
                        questions send one entry per selected option; text and
                        checkbox questions send a single entry.
                    answerId:
                      type: string
                      description: >-
                        ID of a previously stored answer, used when updating an
                        existing answer. Omit when creating a booking.
                  required:
                    - questionId
                    - answer
                description: >-
                  Answers to custom questions scoped to the booked experience as
                  a whole rather than to an individual participant. Same shape
                  as participant-level responses.
              recommendationId:
                type: string
                format: uuid
                nullable: true
                description: >-
                  ID of the listing recommendation that led to this item, stored
                  on the booking for attribution.
                example: 0d9c1f2e-3a4b-4c5d-8e6f-7a8b9c0d1e2f
            required:
              - sessionTime
              - participants
              - mode
              - experienceId
          description: >-
            The cart items to book, one per experience session. Uses the same
            item shape as the payment intent request; all items are booked
            together under the cart identified by cartId.
        purchaser:
          type: object
          properties:
            firstName:
              type: string
              description: Purchaser's first name.
              example: Alice
            lastName:
              type: string
              description: Purchaser's last name.
              example: Rivera
            emailAddress:
              type: string
              pattern: >-
                ^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
              description: >-
                Purchaser's email address. The booking confirmation is sent
                here.
              example: alice@example.com
            phoneNumber:
              type: string
              description: Purchaser's phone number, including country code.
              example: '+15550100'
            customQuestionResponses:
              type: array
              items:
                type: object
                properties:
                  questionId:
                    type: string
                    description: >-
                      ID of the custom question being answered, from the custom
                      questions endpoint.
                    example: q-marketing-optin
                  answer:
                    type: array
                    items:
                      type: object
                      properties:
                        value:
                          oneOf:
                            - type: string
                            - type: boolean
                          description: >-
                            The answer value - the selected option's display
                            value for select questions, free text for text
                            questions, or a boolean for checkboxes.
                          example: 'Yes'
                        key:
                          type: string
                          nullable: true
                          description: >-
                            The selected option's key for select-type questions;
                            null for free-text and checkbox answers.
                          example: 'yes'
                      required:
                        - value
                    description: >-
                      The answer as an array of value/key pairs. Multi-select
                      questions send one entry per selected option; text and
                      checkbox questions send a single entry.
                required:
                  - questionId
                  - answer
              description: >-
                Answers to purchaser-scoped custom questions. Same shape as
                participant-level responses.
          required:
            - firstName
            - lastName
            - emailAddress
          description: >-
            The person paying for the booking, who receives the confirmation
            email. Does not have to be one of the participants.
        loyaltyProgramData:
          type: object
          properties:
            loyaltyProgramId:
              type: string
              description: Identifier of the loyalty program the member belongs to.
              example: WOH
            memberId:
              type: string
              description: The guest's membership number in the loyalty program.
              example: '123456789'
          required:
            - loyaltyProgramId
            - memberId
          description: >-
            Loyalty program membership to associate with the booking, used with
            loyalty payment flows and member benefits.
        paymentMethod:
          type: string
          enum:
            - credit-card
            - room-charge
            - member-number
            - loyalty
            - kicc
            - cash
            - pay-later
            - pay-upon-arrival
          description: >-
            How the guest pays. credit-card goes through Stripe: create a
            payment intent first and confirm the charge after booking. cash,
            room-charge, member-number, loyalty and pay-upon-arrival skip Stripe
            entirely and the booking is confirmed synchronously; room-charge and
            member-number additionally require paymentDetail populated from the
            room-charge validate endpoint. kicc is the KICC payment-gateway
            flow. Any booking with a zero total also confirms synchronously.
          example: credit-card
        paymentDetail:
          type: object
          properties:
            lastName:
              type: string
              description: >-
                Guest's last name on the hotel reservation, matching the name
                used to validate the room charge.
              example: Rivera
            methodNumber:
              type: string
              description: >-
                The number the charge is posted against - the reservation number
                validated via the room-charge validate endpoint for room-charge,
                or the guest's member number for member-number payments.
              example: '84213'
            pmsType:
              type: string
              enum:
                - opera
                - stayntouch
                - infor
                - mews
              description: >-
                The property-management system the room charge posts to. Use the
                same integration type you called the room-charge validate
                endpoint with.
              example: opera
            reservationId:
              oneOf:
                - type: number
                - type: string
              description: >-
                PMS reservation identifier returned by the room-charge validate
                endpoint; pass it through unchanged.
              example: '84213'
            confirmationId:
              type: string
              description: >-
                PMS confirmation identifier returned by the room-charge validate
                endpoint.
              example: '377649'
            collectionDetail:
              type: string
              description: >-
                Free-text detail about how the payment is collected. Shown in
                financial reports as the payment reference when methodNumber is
                absent.
              example: Collected at front desk
          nullable: true
          description: >-
            Payment reference details for non-card methods. Required for
            room-charge and member-number bookings - populate it from the
            room-charge validate response. Omit for card payments.
        bookingScriptUrl:
          type: string
          format: uri
          description: >-
            URL of the page where the booking was made. Stored as the booking's
            source URL for attribution.
          example: https://www.example-hotel.com/experiences
        externalAnalyticsUserId:
          type: string
          description: >-
            Your analytics platform's identifier for the guest. Stored on the
            booking and surfaced in financial reports for cross-system
            attribution.
          example: GA1.2.345678901.1720000000
        siteLanguage:
          type: string
          description: >-
            Language code of the site where the booking was made (e.g. en).
            Stored on the booking and included in booking details and webhooks.
          example: en
        deviceType:
          type: string
          enum:
            - pc
            - mobile
          description: Type of device the guest booked from, recorded for analytics.
          example: pc
        cartId:
          type: string
          format: uuid
          description: >-
            Client-generated UUID (v4 or v7) identifying this checkout's cart -
            there is no create-cart endpoint; Way accepts the ID lazily the
            first time it appears. Use the same cartId as the payment intent so
            Way can correlate booking and payment, and rotate to a fresh UUID
            before retrying a failed checkout.
          example: 14e722e0-048b-4c7b-a70d-5e812b2b761e
        sendEmail:
          type: boolean
          description: >-
            Whether Way sends the guest confirmation emails for this booking.
            Defaults to true.
        convertToUsd:
          default: false
          type: boolean
          description: >-
            When true and the cart's currency is not USD, charges the booking in
            USD using Way's conversion rate. Defaults to false.
        recommendationId:
          type: string
          format: uuid
          nullable: true
          description: >-
            ID of the listing recommendation that led to this checkout, stored
            on the resulting bookings for attribution.
          example: 0d9c1f2e-3a4b-4c5d-8e6f-7a8b9c0d1e2f
      required:
        - data
        - purchaser
    PaymentResultDto:
      type: object
      properties:
        subjectId:
          type: string
          description: The unique identifier of the payment subject.
          example: subject-123
        subjectType:
          type: string
          description: The type of the subject related to the payment.
          example: booking
        confirmationCode:
          type: string
          description: Confirmation code for the payment.
          example: CONFIRM12345
        amount:
          type: number
          description: >-
            Amount of the payment. For card payments this echoes the Stripe
            payment intent and is in minor units (15000 = $150.00); for cash and
            other non-card bookings it is in major units. Prefer the payment
            intent's totalNetAmount or the booking's amount from Get bookings
            for pricing.
          example: 17800
        currency:
          type: string
          description: Currency of the transaction.
          example: USD
        clientSecret:
          type: object
          description: >-
            Stripe client secret to confirm the payment with (card payments
            only); null for cash and other non-card bookings.
          example: pi_3NxA7bK2eZ_secret_Yz4Q8w
        metadata:
          type: object
          description: Additional metadata related to the payment.
          example:
            transactionId: txn-789
          nullable: true
      required:
        - subjectId
        - subjectType
        - confirmationCode
        - amount
        - currency
  securitySchemes:
    Brand-API-Key:
      type: http
      scheme: bearer
      description: >-
        Your brand's secret API key, e.g. `Bearer
        way_sk_live_bhEqcn0i1fRoUEHBPjJkQA`. Older `Way-Brand-Id` +
        `Way-Secret-Key` credentials still work: see [Legacy
        authentication](/legacy-authentication).
    Organization-API-Key:
      type: http
      scheme: bearer
      description: >-
        Your organization's secret API key, e.g. `Bearer
        way_sk_live_ohEqcn0i1fRoUEHBPjJkQA`. Older `Way-Organization-Id` +
        `Way-Secret-Key` credentials still work: see [Legacy
        authentication](/legacy-authentication).

````