openapi: 3.1.0
info:
  title: TTDbooking Stays API
  version: 1.0.0
  summary: Hotel search, booking and order management for travel distribution partners.
  description: |-
    The TTDbooking Stays API lets distribution partners search hotel availability,
    hold and confirm reservations, and manage orders after booking.

    Every endpoint is `POST` and exchanges JSON. Every response uses the same
    envelope — `{ "code": 0, "msg": "success", "data": { ... } }` — and `code` is
    authoritative: some business failures are delivered with HTTP 200, so check
    `code` rather than the transport status alone.

    Authenticate by exchanging your `appKey`/`appSecret` for a ticket at
    `POST /api/auth/ticket`, then send `Authorization: Bearer <ticket>` on every
    other call. A ticket expires at a fixed time set when it is issued; it is
    meant to be cached and reused until then, not minted per request.

    Bookings follow a four-step funnel: HotelList → HotelRates → CheckAvail →
    Book, then QueryOrders or Cancel to manage the result.

    **Limits.** Each endpoint carries a per-second ceiling, counted per endpoint per
    client IP: 100/second on search and content, 50/second on QueryOrders, 10/second on
    CheckAvail, Book and Cancel, and 5/second on ticket issuance. Responses carry
    `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and a `429`
    carries `Retry-After` and `code` 100000429. See
    https://developer.ttdbooking.com/hotel-api/docs/guides/rate-limit.

    Migrating an existing integration? See the migration guide at
    https://developer.ttdbooking.com/hotel-api/docs/guides/migrating-to-ttdbooking.
  contact:
    name: TTDbooking Partner Support
    email: info@ttdbooking.com
    url: https://developer.ttdbooking.com/hotel-api/docs
servers:
  - url: https://api.ttdbooking.com
    description: Production
  - url: https://api-test.ttdbooking.com
    description: Test / sandbox
tags:
  - name: Authentication
    description: Exchange credentials for a bearer ticket.
  - name: Content
    description: Destination hierarchies and hotel static content.
  - name: Search
    description: Availability and rate discovery.
  - name: Make bookings
    description: Revalidate a rate and place the reservation.
  - name: Manage bookings
    description: Retrieve, poll and cancel orders.
# Two alternatives, not two requirements: an OpenAPI security LIST is an OR, so
# an operation is satisfied by a ticket or by an OAuth 2.0 access token. Both
# arrive in the same `Authorization: Bearer` header and TradeApiAuthGuard tells
# them apart by shape (a ticket is a JWT; an access token is opaque).
# `ticketAuth` is listed first so a generator that picks the first scheme keeps
# emitting the flow every existing integration already uses.
security:
  - ticketAuth: []
  - oauth2ClientCredentials:
      - search:read
      - content:read
      - booking:read
      - booking:write
      - booking:cancel
paths:
  /api/auth/ticket:
    post:
      summary: Ticket
      operationId: ticket
      deprecated: false
      description: |-
        Exchanges an appKey/appSecret pair for an authentication token (a
        "ticket", in JWT form) that must accompany every subsequent API request.

        **Expiry model**

        - Expiry is ABSOLUTE and fixed at issuance. It is not extended by API
          activity, and no renewed ticket is ever returned on a subsequent call.
        - TTL parameter: the ticket's total lifetime in seconds, counted from
          issuance. Defaults to 24 hours (86400) when not supplied.
        - The response's `expiresAt` is the authoritative expiry instant (Unix
          seconds). Treat it as final for that ticket.
        - The TTL you request IS the lifetime. It must be a positive number of
          seconds and may not exceed 365 days (31536000); larger values are
          rejected. That ceiling bounds what you may ask for — it is not an
          additional expiry running alongside the TTL.

        **Usage guidelines**

        - Cache the ticket and reuse it until `expiresAt`, then request a new
          one.
        - Do NOT call this endpoint before every API call — it is expensive and
          unnecessary.
        - Renew proactively, shortly before `expiresAt`. Because expiry is
          absolute, a busy integration will still expire on schedule.
        - Send the ticket in the Authorization header as: "Bearer <ticket>".

        **Error handling**

        - 401: appKey/appSecret is invalid — contact your TTDbooking
          representative.
        - 401: the ticket has reached `expiresAt` — call this endpoint again for
          a new one.
        - 429: rate limit exceeded — wait before retrying.
      tags:
        - Authentication
      security: []
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: Client request time (when the client began sending the request), as a unix timestamp.
          required: false
          example: 0
          schema:
            type: integer
            format: int64
            description: client request time(start to send request); unix timestamp
        - name: IP
          in: header
          description: Client IP address; accepts both IPv4 and IPv6.
          required: false
          example: ""
          schema:
            type: string
            description: client IP address, compatible with both IPv4 and IPv6
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag, e.g. "en" or "en-US". Defaults to "en-US". Source cites
            https://masonreview.com/posts/ietf-bcp-47-language-tags/ as the reference for the tag
            format.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
              "en-US"
        - name: Request-Id
          in: header
          description: Identifies this single request; values must not repeat.
          required: false
          example: ""
          schema:
            type: string
            description: for identifying the current request, it can't be duplicate
        - name: Trace-Id
          in: header
          description: Correlates a group of related requests.
          required: false
          example: ""
          schema:
            type: string
            description: for tracing a group of requests
        - name: Authorization
          in: header
          description: >-
            Begins with "Bearer ". Obtained from the Ticket response. The Ticket endpoint itself
            does not require it.
          required: false
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.api.protocol.TicketReq"
            examples:
              default:
                summary: Ticket request assembled from the source field-level examples
                description: >-
                  The source document provides no whole-body example; this is composed from the
                  per-field `examples` entries on appKey, appSecret and ttl.
                value:
                  appKey: ttdbooking_api_demo
                  appSecret: ttdbooking_api_demo
                  ttl: 3600
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TicketRespEnvelope"
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: >-
            Unauthorized. Either the appKey/appSecret pair is invalid (contact your TTDbooking
            representative) or the token has expired through inactivity — request a new ticket from
            this endpoint.
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests — rate limit exceeded; wait before retrying.
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/search/destinations:
    post:
      operationId: destinations
      summary: Destinations
      deprecated: false
      tags:
        - Content
      description: >-
        Returns destination records - either standard or detailed - selected by a parent destination
        ancestor ID or by a country code. The data is hierarchical and intended for hotel booking
        clients.


        **Two ways to query**


        1. *By parent destination ID* - supply `parentDestinationId` to retrieve the immediate
        children of that destination. Useful when walking a location tree (for example, the cities
        that sit under a state).


        2. *By country code* - supply `countryCode` in ISO 3166-1 alpha-2 form (for example `US`,
        `CN`) to retrieve the top-level destinations of that country. When `countryCode` is present,
        `parentDestinationId` is disregarded.


        **Levels of detail returned**


        - `standard` (the default): metadata plus basic hierarchy for each region.

        - `details`: metadata plus coordinates and the complete hierarchy for each region.


        **Typical uses**


        - Populating location pickers on booking forms.

        - Progressive location narrowing (country, then state, then city).

        - Autocomplete over geographic search.


        **Performance**


        - Responses are served from cache.

        - A large country can yield a high destination count; paginate in the UI if needed.
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: Unix timestamp recorded by the client at the moment it began sending the request.
          required: false
          example: 0
          schema:
            type: integer
            format: int64
            description: Unix timestamp recorded by the client at the moment it began sending the request.
        - name: IP
          in: header
          description: Client IP address; both IPv4 and IPv6 are accepted.
          required: false
          example: ""
          schema:
            type: string
            description: Client IP address; both IPv4 and IPv6 are accepted.
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag, for example "en" or "en-US". Defaults to "en-US" when omitted.
            Reference: https://masonreview.com/posts/ietf-bcp-47-language-tags/
          required: false
          example: ""
          schema:
            type: string
            description: >-
              IETF BCP 47 language tag, for example "en" or "en-US". Defaults to "en-US" when
              omitted. Reference: https://masonreview.com/posts/ietf-bcp-47-language-tags/
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: Identifies this single request; the value must not repeat across requests.
          required: false
          example: ""
          schema:
            type: string
            description: Identifies this single request; the value must not repeat across requests.
        - name: Trace-Id
          in: header
          description: Correlates a group of related requests for tracing.
          required: false
          example: ""
          schema:
            type: string
            description: Correlates a group of related requests for tracing.
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: >-
            Bearer credential. The value begins with the literal prefix "Bearer " and the token is
            obtained from the Ticket response. The Ticket endpoint itself does not require this
            header.
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.search.protocol.DestinationsReq"
            examples:
              byCountryCode:
                summary: Query by country code
                description: >-
                  Uses the `countryCode` value carried in the source field-level example.
                  `parentDestinationId` is ignored in this mode.
                value:
                  countryCode: AE
              byParentDestinationId:
                summary: Query by parent destination ID
                description: Uses the `parentDestinationId` value carried in the source field-level example.
                value:
                  parentDestinationId: "804028047"
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DestinationsRespEnvelope"
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/search/hotelStaticDetail:
    post:
      operationId: hotelStaticDetail
      summary: HotelStaticDetail
      deprecated: false
      description: >-
        ⚠️ [DEVELOPMENT] Not yet finished — do not build production traffic on this endpoint; use
        the HotelsMetadata API instead for production.


        Fetches the full static profile of one hotel: core identity fields, facilities, imagery,
        contact details and geo/location data.


        **Primary Use Cases:**

        - Rendering a hotel detail page

        - Enriching a booking flow with hotel content

        - Managing hotel profiles inside a CMS


        **Required Parameters:**

        - **hotelId**: unique hotel identifier (required)


        **Integration Notes:**

        - Returns a detailed hotel profile localised into EN / ZH / AR

        - Carries hotel facilities, imagery and contact details

        - Supplies geo coordinates plus destination information

        - Intended for hotel detail rendering and content administration
      tags:
        - Content
      parameters:
        - $ref: "#/components/parameters/ClientRequestTimestamp"
        - $ref: "#/components/parameters/IP"
        - $ref: "#/components/parameters/Language"
        - $ref: "#/components/parameters/Market"
        - $ref: "#/components/parameters/RequestId"
        - $ref: "#/components/parameters/TraceId"
        - $ref: "#/components/parameters/UserRef"
        - $ref: "#/components/parameters/Authorization"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.search.protocol.HotelStaticDetailReq"
            examples:
              default:
                summary: Minimal request — hotelId only
                value:
                  hotelId: "461850557"
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelStaticDetailRespEnvelope"
              examples:
                default:
                  summary: Response assembled from the per-field `examples` in the source
                  value:
                    code: 0
                    msg: ""
                    data:
                      hotel:
                        id: "461850557"
                        destinationId: "804028047"
                        name:
                          en: Jumeirah Beach Hotel
                        rating: 4.5
                        address:
                          en: Millenium Al Barsha
                        latlngCoordinator:
                          google:
                            lat: 25.0478
                            lng: 121.5319
                          gaode:
                            lat: 25.0478
                            lng: 121.5319
                        logoURL: https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
                        minPrice:
                          amount: 100
                          currency: USD
                        minPricesByCurrency:
                          - amount: 700
                            currency: CNY
                          - amount: 85
                            currency: EUR
                        isAvailable: true
                        rooms:
                          - roomTypeId: R001
                            roomTypeName:
                              en: Standard Room
                            hotelId: "461850557"
                            rates:
                              - ratePkgId: ""
                                refundableMode: full
                                refundableUntil: 2006-01-02T15:04:05Z07:00
                                rate:
                                  netRate:
                                    currency: USD
                                    amount: 14.5
                                totalRate:
                                  netRate:
                                    currency: USD
                                    amount: 14.5
                                checkIn: "2026-01-01"
                                checkOut: "2026-01-03"
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/search/hotelsMetadata:
    post:
      operationId: hotelsMetadata
      summary: HotelsMetadata
      description: >-
        Returns paginated hotel metadata for a single destination.


        Use this endpoint to enumerate the hotels that belong to a destination and pull their
        descriptive attributes (identifier, localised name and address, star rating, coordinates,
        logo image). It is aimed at catalogue and content workflows rather than at live
        availability.


        **Primary use cases**

        - Browsing a hotel catalogue one destination at a time

        - Populating hotel listings inside a CMS

        - Enriching search interfaces with hotel metadata


        **Required parameters**

        - `destinationId` — the unique identifier of the destination


        **Integration notes**

        - Intended for content and catalogue operations

        - Suitable for building hotel-selection UIs

        - Supports incremental synchronisation of hotel metadata
      deprecated: false
      tags:
        - Content
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: Time at which the client began sending the request, expressed as a Unix timestamp.
          required: false
          example: 0
          schema:
            type: integer
            format: int64
            description: client request time(start to send request); unix timestamp
        - name: IP
          in: header
          description: Client IP address. Both IPv4 and IPv6 are accepted.
          required: false
          example: ""
          schema:
            type: string
            description: client IP address, compatible with both IPv4 and IPv6
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag, for example "en" or "en-US". Defaults to "en-US" when omitted.
            Reference: https://masonreview.com/posts/ietf-bcp-47-language-tags/
          required: false
          example: ""
          schema:
            type: string
            description: >-
              https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
              "en-US"
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: Identifier for this single request. Values must not be reused across requests.
          required: false
          example: ""
          schema:
            type: string
            description: for identifying the current request, it can't be duplicate
        - name: Trace-Id
          in: header
          description: Correlation identifier used to trace a group of related requests.
          required: false
          example: ""
          schema:
            type: string
            description: for tracing a group of requests
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: >-
            Bearer credential. The value must start with "Bearer " followed by the token returned by
            the Ticket endpoint. The Ticket endpoint itself does not require this header.
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.search.protocol.HotelsMetadataReq"
            examples:
              composedFromFieldExamples:
                summary: Request composed from the per-field examples in the source
                description: >-
                  The source document contains no whole-body example. This example is assembled from
                  the individual field-level examples ('804028047', 'AE', 1, 20, 0) and is therefore
                  illustrative rather than verbatim.
                value:
                  destinationId: "804028047"
                  countryCode: AE
                  page:
                    pageNum: 1
                    pageSize: 20
                    cursor: 0
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelsMetadataListRespEnvelope"
              examples:
                composedFromFieldExamples:
                  summary: Response composed from the per-field examples in the source
                  description: >-
                    The source document contains no whole-body example. This example is assembled
                    from the individual field-level examples. `code` and `msg` carry no documented
                    example values in the source and are shown here as null.
                  value:
                    code: null
                    msg: null
                    data:
                      hotelsMetadata:
                        - hotelId: null
                          destinationId: "804028047"
                          name:
                            en: Jumeirah Beach Hotel
                          rating: 4.5
                          address:
                            en: Millenium Al Barsha
                          latlngCoordinator:
                            google:
                              lat: 25.0478
                              lng: 121.5319
                            gaode:
                              lat: 25.0478
                              lng: 121.5319
                          logoURL: https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
                      page:
                        total: 100
                        hasMore: true
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/search/hotelList:
    post:
      operationId: hotelList
      summary: HotelList
      description: >-
        Returns hotels matching a set of search criteria — destination, stay dates and guest
        configuration — with optional per-hotel room availability and pricing.


        Three ways to drive the search are supported:


        1. **By specific SupplierHotelList** — pass explicit hotel IDs to fetch detail for exactly
        those properties.

        2. **By destination** — search within a region, addressed either by `destinationId` or by
        `destinationName`.

        3. **By location** — return hotels near a point, ranked by distance.


        **Required parameters**


        - `checkIn` / `checkOut` — the stay dates.

        - `roomOccupancies` — one entry per room, each carrying `adultCount` and optional
        `childrenAges`. At least one entry is required.

        - at least one of `destinationId`, `destinationName` or `hotelIds` — how the search is
        scoped. A body carrying none of the three is rejected.


        **Optional parameters**


        - `destinationId` — region identifier for a location-scoped search.

        - `destinationName` — region name; the server resolves it to an ID.

        - `hotelIds` — explicit hotel IDs to retrieve.

        - `maxRatesPerHotel` — cap on room rates returned per hotel; 0 (the default) is uncapped.

        - `sortBy` — result ordering (price-asc, price-desc, rating-desc, distance-asc).

        - `pageNum` / `pageSize` / `cursor` — pagination controls. They are flat top-level fields on
        this endpoint; the nested `page` object belongs to HotelsMetadata, not here. `pageSize`
        defaults to 50 and is capped at 200; a larger value is rejected rather than clamped.


        **What comes back**


        - A hotel list carrying core property information.

        - Room availability and pricing, when requested.

        - Pagination metadata for large result sets.

        - A session identifier that ties the search context together.

        - `basic.statusRemark` / `basic.notices` / `basic.emptyReason` — why a result is empty or
        incomplete. See "Empty results" below.


        **Empty results**


        `{ "list": [], "total": 0 }` has two causes that need opposite responses, and on its own it
        cannot tell you which you have hit:


        1. **The suppliers were asked and had nothing.** Genuine zero availability — try other dates
        or another property. `basic.emptyReason` is ABSENT.

        2. **No supplier answered, or none was asked at all.** A configuration state on our side.
        Retrying the same request, or changing the dates or the destination, cannot change it.
        `basic.emptyReason.code` is present and says which.


        `basic.emptyReason.code` is one of:


        - `NO_SUPPLIER_ENABLED` — no supplier is currently enabled for hotel search.

        - `NO_SUPPLIER_PERMITTED` — suppliers are enabled, but none may serve your account on this
        search.

        - `ALL_SUPPLIERS_EXCLUDED` — every candidate was excluded before the search ran, by a
        market, currency, language or inventory restriction.

        - `NO_SUPPLIER_ANSWERED` — suppliers were called and every one of them failed. This is the
        only one of the four worth retrying.


        `basic.statusRemark` carries the same thing as one human-readable sentence, suitable for a
        log line or an operator-facing message.


        `basic.emptyReason.suppliers` — WHICH supplier failed and why — is disclosed only to
        accounts entitled to the supplier breakdown. Most integrations will never see it, and its
        absence is not an error: the `code` and the `statusRemark` are complete without it.


        `basic.notices` is separate and belongs to a search that WORKED: it lists what the response
        does not contain when the result is real but not complete (a destination expansion that hit
        its cap, properties dropped because they could not be priced in the requested currency). It
        is not emitted alongside `emptyReason` — on an empty response there is no partial result for
        it to qualify, and `statusRemark` already carries the explanation.


        All four fields are additive and optional. A client that ignores them behaves exactly as it
        did before they existed.


        **Typical uses**


        - Powering a hotel booking search UI.

        - Browsing the inventory of a destination.

        - Looking up one or more known properties.

        - Suggesting hotels near a given point.
      deprecated: false
      tags:
        - Search
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: Unix timestamp recorded by the client at the moment it begins sending the request.
          required: false
          example: 0
          schema:
            description: Unix timestamp recorded by the client at the moment it begins sending the request.
            type: integer
            format: int64
        - name: Currency
          in: header
          description: >-
            Currency the rates should be quoted in, expressed as an ISO 4217 code
            (https://en.wikipedia.org/wiki/ISO_4217).
          required: false
          example: ""
          schema:
            description: >-
              Currency the rates should be quoted in, expressed as an ISO 4217 code
              (https://en.wikipedia.org/wiki/ISO_4217).
            type: string
        - name: IP
          in: header
          description: Client IP address; both IPv4 and IPv6 are accepted.
          required: false
          example: ""
          schema:
            description: Client IP address; both IPv4 and IPv6 are accepted.
            type: string
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag (https://masonreview.com/posts/ietf-bcp-47-language-tags/), for
            example "en" or "en-US". Defaults to "en-US".
          required: false
          example: ""
          schema:
            description: >-
              IETF BCP 47 language tag (https://masonreview.com/posts/ietf-bcp-47-language-tags/),
              for example "en" or "en-US". Defaults to "en-US".
            type: string
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: Identifies this individual request; values must not repeat.
          required: false
          example: ""
          schema:
            description: Identifies this individual request; values must not repeat.
            type: string
        - name: Session-Id
          in: header
          description: >-
            Recommended to be supplied by the client on every call, and mandatory throughout the
            booking flow.
          required: true
          example: ""
          schema:
            description: >-
              Recommended to be supplied by the client on every call, and mandatory throughout the
              booking flow.
            type: string
        - name: Test
          in: header
          description: >-
            Test switches, given as key-value pairs — for example "hotel=HC1&scenario=priceChange".
            A value the server does not recognise is ignored, and the call proceeds exactly as if no
            "Test" header had been sent.
          required: false
          example: ""
          schema:
            description: >-
              Test switches, given as key-value pairs — for example
              "hotel=HC1&scenario=priceChange". A value the server does not recognise is ignored,
              and the call proceeds exactly as if no "Test" header had been sent.
            type: string
        - name: Timeout-Milliseconds
          in: header
          description: Client-imposed timeout; the server makes a best effort to respond within it.
          required: false
          example: 0
          schema:
            description: Client-imposed timeout; the server makes a best effort to respond within it.
            type: integer
            format: int64
        - name: Trace-Id
          in: header
          description: Correlates a group of related requests for tracing.
          required: false
          example: ""
          schema:
            description: Correlates a group of related requests for tracing.
            type: string
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: >-
            Must begin with "Bearer ". The token is obtained from the Ticket response; the Ticket
            call itself does not require this header.
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.search.protocol.HotelListReq"
            examples:
              byDestinationName:
                summary: Destination-name search (assembled from the per-field examples in the source)
                value:
                  hotelIds:
                    - "461850557"
                    - "118062388"
                  maxRatesPerHotel: 3
                  checkIn: "2026-01-01"
                  checkOut: "2026-01-03"
                  countryCode: US
                  residencyCode: US
                  nationalityCode: US
                  roomOccupancies:
                    - adultCount: 2
                      childrenAges:
                        - 2
                  destinationId: "804028047"
                  destinationName: Dubai
                  pageNum: 1
                  pageSize: 50
                  cursor: 0
                  sortBy: price-desc
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                title: HotelListResp
                type: object
                properties:
                  code:
                    type: integer
                  msg:
                    type: string
                  data:
                    $ref: "#/components/schemas/hotel.search.protocol.HotelListResp"
                x-display-name: hotel.search.protocol.HotelListResp
                x-primary-property: data
              examples:
                success:
                  summary: Successful search (assembled from the per-field examples in the source)
                  value:
                    data:
                      list:
                        - id: "461850557"
                          destinationId: "804028047"
                          name:
                            en: Jumeirah Beach Hotel
                          rating: 4.5
                          address:
                            en: Millenium Al Barsha
                          latlngCoordinator:
                            google:
                              lat: 25.0478
                              lng: 121.5319
                            gaode:
                              lat: 25.0478
                              lng: 121.5319
                          logoURL: https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
                          minPrice:
                            amount: 100
                            currency: USD
                          minPricesByCurrency:
                            - amount: 700
                              currency: CNY
                            - amount: 85
                              currency: EUR
                          isAvailable: true
                      basic:
                        destination:
                          id: "804028047"
                          name:
                            en: Dubai
                        sessionId: 374337a797454a344ad999c7730da01c
                      total: 100
                      hasMore: true
                emptyDiagnosed:
                  summary: >-
                    Empty for a configuration reason, as most partners see it — the neutral code and
                    remark, no supplier named
                  value:
                    code: 0
                    msg: success
                    data:
                      list: []
                      basic:
                        destination:
                          id: Dubai
                        sessionId: 4XbSCe8AZ2Qk1sTsAVJEUeeBBBoW2ONA
                        statusRemark: >-
                          No supplier was searched for this request: no supplier is currently
                          enabled for hotel search. This is a configuration state, not an absence of
                          availability — retrying, or changing the dates or destination, will not
                          change it. Contact your account manager.
                        emptyReason:
                          code: NO_SUPPLIER_ENABLED
                      total: 0
                      hasMore: false
                emptyDiagnosedWithBreakdown:
                  summary: >-
                    The same state seen by an account entitled to the supplier breakdown — the
                    detailed remark and the per-supplier list
                  value:
                    code: 0
                    msg: success
                    data:
                      list: []
                      basic:
                        destination:
                          id: Dubai
                        sessionId: r9dj5Yx1LEnRBM0hEIsp4S2fFDlvxpOa
                        statusRemark: >-
                          No supplier returned a result: MOCK (TIMEOUT: supplier did not respond
                          within 20000 ms)
                        emptyReason:
                          code: NO_SUPPLIER_ANSWERED
                          suppliers:
                            - supplierCode: MOCK
                              reason: "TIMEOUT: supplier did not respond within 20000 ms"
                      total: 0
                      hasMore: false
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/search/hotelRates:
    post:
      summary: HotelRates
      operationId: hotelRates
      deprecated: false
      description: |-
        Returns room-level rates and availability for one specific hotel, across all
        connected suppliers.

        Where HotelList covers many hotels with summary rate data, this call is scoped to a
        single hotel and returns the full rate detail needed to drive a booking. Every
        supplier supports detailed rate queries on this endpoint.

        Required inputs:
        - `hotelId` — identifier of the hotel to price
        - `checkIn` / `checkOut` — stay dates
        - occupancies — guest and room layout (sent as the `roomOccupancies` body field; see
          the note in the schema, the prose in the source calls this "occupancies")
        - `Session-Id` request header — carries the session used to track the booking process

        What comes back:
        - Full room-package detail including rates
        - Standardized/mapped room types alongside the supplier's own room naming
        - Session context so the result can be carried into the booking flow

        Typical uses: rendering rates on a hotel detail page, comparing and selecting a room,
        and starting a detailed booking flow.

        Integration guidance: use HotelList for multi-hotel searches with basic rate data, use
        HotelRates for single-hotel detail, and keep the session identifier consistent so the
        transition into booking is seamless.
      tags:
        - Search
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: client request time(start to send request); unix timestamp
          required: false
          example: 0
          schema:
            description: client request time(start to send request); unix timestamp
            format: int64
            type: integer
        - name: Currency
          in: header
          description: Requested currency for the rates, in https://en.wikipedia.org/wiki/ISO_4217 format
          required: false
          example: ""
          schema:
            description: Requested currency for the rates, in https://en.wikipedia.org/wiki/ISO_4217 format
            type: string
        - name: IP
          in: header
          description: client IP address, compatible with both IPv4 and IPv6
          required: false
          example: ""
          schema:
            description: client IP address, compatible with both IPv4 and IPv6
            type: string
        - name: Language
          in: header
          description: >-
            https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
            "en-US"
          required: false
          example: ""
          schema:
            description: >-
              https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
              "en-US"
            type: string
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: for identifying the current request, it can't be duplicate
          required: false
          example: ""
          schema:
            description: for identifying the current request, it can't be duplicate
            type: string
        - name: Session-Id
          in: header
          description: Suggested provided in request by client. It's required in booking flow.
          required: true
          example: ""
          schema:
            description: Suggested provided in request by client. It's required in booking flow.
            type: string
        - name: Test
          in: header
          description: >-
            Test flags. support key-value pairs, eg, "hotel=HC1&scenario=priceChange".If it's not
            recognized by server, the call will behave as if the "Test" header was not provided.
          required: false
          example: ""
          schema:
            description: >-
              Test flags. support key-value pairs, eg, "hotel=HC1&scenario=priceChange".If it's not
              recognized by server, the call will behave as if the "Test" header was not provided.
            type: string
        - name: Timeout-Milliseconds
          in: header
          description: >-
            timeout specified by client, and server will try its best to return data before this
            timeout
          required: false
          example: 0
          schema:
            description: >-
              timeout specified by client, and server will try its best to return data before this
              timeout
            format: int64
            type: integer
        - name: Trace-Id
          in: header
          description: for tracing a group of requests
          required: false
          example: ""
          schema:
            description: for tracing a group of requests
            type: string
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: starts with "Bearer ". got from Ticket response. Ticket doesn't need it
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.search.protocol.HotelRatesReq"
            examples:
              composedFromFieldLevelExamples:
                summary: Request body composed from the source's per-field examples
                description: >-
                  The source document contains no whole-payload request example. This example is
                  assembled strictly from the `examples` values declared on each individual property
                  (hotelId, checkIn, checkOut, countryCode, residencyCode, nationalityCode,
                  adultCount, childrenAges) and introduces no invented values.
                value:
                  hotelId: "461850557"
                  checkIn: "2026-01-01"
                  checkOut: "2026-01-03"
                  countryCode: US
                  residencyCode: US
                  nationalityCode: US
                  roomOccupancies:
                    - adultCount: 2
                      childrenAges:
                        - 2
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HotelRatesRespEnvelope"
          headers: {}
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/search/checkAvail:
    post:
      operationId: checkAvail
      summary: CheckAvail
      deprecated: false
      tags:
        - Make bookings
      description: >-
        Re-validates a single rate package immediately before booking, confirming that the room is
        still sellable and that the price has not moved since HotelRates returned it.


        This call is the mandatory pre-booking validation step. Skipping it exposes the booking to
        three failure modes:

        - room inventory being consumed between the search and the booking attempt

        - price movement that changes what the traveller was quoted

        - outright booking failure because the rate package is no longer sellable


        **When to call it**

        Call it after HotelRates, once the user has picked one specific rate package.


        **Inputs required**

        - `ratePkgId` (request body): the rate package identifier taken from the HotelRates response

        - `Session-Id` (request header): identifies the session for the booking flow


        **What comes back**

        - the confirmed availability status

        - the final price

        - the refreshed rate package detail

        - fallback candidates for smart booking (R2 candidates)


        **Error behaviour**

        - a price or inventory move is returned in-band: the room comes back
          AVAILABLE with the refreshed rate package and `code` 0, carrying a
          `statusRemark` such as "price updated by supplier revalidation"

        - a rate that has gone entirely comes back UNAVAILABLE with `code` 0 —
          CheckAvail never substitutes a bare error code for the re-priced package

        - the ARI-changed business `code` 100001111 is raised by Book, not here:
          it fires only when the rate moves between this call and the commit,
          where there is no longer a re-priced package to hand back


        **Position in the booking flow**

        1. HotelRates returns the sellable room options

        2. the user picks one rate package

        3. CheckAvail re-validates that pick (this endpoint)

        4. booking proceeds if availability was confirmed

        5. a moved price or reduced inventory is reflected in the refreshed
           package this call returns


        **Typical uses**

        - confirming availability ahead of booking

        - final price check before taking payment

        - preparing the smart-booking fallback

        - detecting inventory movement
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: Unix timestamp recorded by the client at the moment it began sending the request.
          required: false
          example: 0
          schema:
            description: Unix timestamp recorded by the client at the moment it began sending the request.
            type: integer
            format: int64
        - name: Currency
          in: header
          description: >-
            Currency the rates should be returned in, expressed as an ISO 4217 code
            (https://en.wikipedia.org/wiki/ISO_4217).
          required: false
          example: ""
          schema:
            description: >-
              Currency the rates should be returned in, expressed as an ISO 4217 code
              (https://en.wikipedia.org/wiki/ISO_4217).
            type: string
        - name: IP
          in: header
          description: Client IP address. Both IPv4 and IPv6 are accepted.
          required: false
          example: ""
          schema:
            description: Client IP address. Both IPv4 and IPv6 are accepted.
            type: string
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag (https://masonreview.com/posts/ietf-bcp-47-language-tags/), for
            example "en" or "en-US". Defaults to "en-US".
          required: false
          example: ""
          schema:
            description: >-
              IETF BCP 47 language tag (https://masonreview.com/posts/ietf-bcp-47-language-tags/),
              for example "en" or "en-US". Defaults to "en-US".
            type: string
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: Identifies this individual request. Values must not repeat across requests.
          required: false
          example: ""
          schema:
            description: Identifies this individual request. Values must not repeat across requests.
            type: string
        - name: Session-Id
          in: header
          description: >-
            Session identifier. The client is expected to supply it on the request, and it is
            mandatory throughout the booking flow.
          required: true
          example: ""
          schema:
            description: >-
              Session identifier. The client is expected to supply it on the request, and it is
              mandatory throughout the booking flow.
            type: string
        - name: Test
          in: header
          description: >-
            Test flags, supplied as key-value pairs, for example "hotel=HC1&scenario=priceChange".
            When the server does not recognise the value, the request behaves exactly as though no
            "Test" header had been sent.
          required: false
          example: ""
          schema:
            description: >-
              Test flags, supplied as key-value pairs, for example "hotel=HC1&scenario=priceChange".
              When the server does not recognise the value, the request behaves exactly as though no
              "Test" header had been sent.
            type: string
        - name: Timeout-Milliseconds
          in: header
          description: Client-specified timeout; the server makes a best effort to respond within it.
          required: false
          example: 0
          schema:
            description: Client-specified timeout; the server makes a best effort to respond within it.
            type: integer
            format: int64
        - name: Trace-Id
          in: header
          description: Correlates a group of related requests for tracing.
          required: false
          example: ""
          schema:
            description: Correlates a group of related requests for tracing.
            type: string
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: >-
            Bearer credential, prefixed with "Bearer ". Obtained from the Ticket response. The
            Ticket endpoint itself does not require it.
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.search.protocol.CheckAvailReq"
            examples:
              fromSearchResult:
                summary: Recheck a rate package returned by hotelList or hotelRates
                description: >-
                  `ratePkgId` is opaque and is only resolvable inside the session that produced it,
                  so send the `Session-Id` you received from hotelList alongside this body.
                value:
                  ratePkgId: rp_8f3c1a7e6b2d40f9a51c
      responses:
        "200":
          description: >-
            Success envelope. A price or inventory move is returned in-band as a
            CheckAvailResp: the room comes back AVAILABLE with the refreshed rate
            package and `code` 0, carrying a `statusRemark` such as "price updated by
            supplier revalidation"; a rate that has gone comes back UNAVAILABLE with
            `code` 0. CheckAvail does not emit the ARI-changed business code
            100001111 — that is raised by Book when the rate moves between this call
            and the commit (see the Book endpoint's 200 response).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CheckAvailResp"
              examples:
                priceUpdated:
                  summary: Supplier re-priced the rate (still available)
                  description: >-
                    The refreshed, marked-up rate package is returned with `code` 0 and
                    a statusRemark; the stable ratePkgId is carried straight into Book.
                  value:
                    code: 0
                    msg: success
                    data:
                      status: 1
                      statusRemark: price updated by supplier revalidation
          headers: {}
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/trade/book:
    post:
      summary: Book
      operationId: book
      deprecated: false
      tags:
        - Make bookings
      description: >-
        Places a hotel booking order that reserves a room against a specific rate package.


        This is the terminating call of the hotel booking flow. It creates a confirmed reservation
        with the supplier and covers pre-paid account deduction, order creation and the platform's
        reliability mechanisms.


        **Critical Prerequisites:**

        - **SessionId (REQUIRED in Header)**: must be supplied so the booking process can be tracked

        - **Must be called after CheckAvail**: guarantees the rate package is still available

        - **JWT Authentication**: an Authorization header carrying a Bearer token is required


        **Required Parameters:**

        - **customerReferenceNo**: the booking's reference number

        - **ratePkgId**: the rate package id being booked

        - **holder**: holder details for the booking

        - **guests**: guest details for the booking

        - **sessionId (in Header)**: session id used to track the booking process


        **Booking Flow Integration:**

        1. **Search**: call HotelRates to retrieve available room options

        2. **Select**: the user picks one rate package

        3. **Verify**: call CheckAvail to re-confirm availability and price

        4. **Book**: call Book to place the final reservation - this step

        5. **Confirm**: query the order status to verify the booking succeeded


        **Idempotency:**

        - Requests are idempotent on customerReferenceNo

        - A duplicate request carrying the same identifiers returns the already-created order

        - This is what prevents accidental double bookings


        **Enterprise Reliability Features:**

        - Order status tracking and confirmation

        - Session management for booking context

        - Transaction rollback when a call fails


        **Response Features:**

        - Confirmed booking details

        - Supplier reference numbers

        - Order tracking information


        **Error Handling:**

        - Timeout errors when the upstream or supplier is slow

        - Reliability mechanisms covering booking failures

        - Order rollback on critical failures


        **Common Use Cases:**

        - Final confirmation of a hotel reservation
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: Time the client began sending the request, as a unix timestamp.
          required: false
          example: 0
          schema:
            description: client request time(start to send request); unix timestamp
            type: integer
            format: int64
        - name: Currency
          in: header
          description: >-
            Currency the rates should be returned in, as an ISO 4217 code
            (https://en.wikipedia.org/wiki/ISO_4217).
          required: false
          example: ""
          schema:
            description: Requested currency for the rates, in https://en.wikipedia.org/wiki/ISO_4217 format
            type: string
        - name: IP
          in: header
          description: Client IP address. Both IPv4 and IPv6 are accepted.
          required: false
          example: ""
          schema:
            description: client IP address, compatible with both IPv4 and IPv6
            type: string
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag (https://masonreview.com/posts/ietf-bcp-47-language-tags/), for
            example "en" or "en-US". Defaults to "en-US".
          required: false
          example: ""
          schema:
            description: >-
              https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
              "en-US"
            type: string
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: Identifies this single request. Must not be reused across requests.
          required: false
          example: ""
          schema:
            description: for identifying the current request, it can't be duplicate
            type: string
        - name: Session-Id
          in: header
          description: Recommended on every client request, and mandatory throughout the booking flow.
          required: true
          example: ""
          schema:
            description: Suggested provided in request by client. It's required in booking flow.
            type: string
        - name: Test
          in: header
          description: >-
            Test flags, expressed as key-value pairs such as "hotel=HC1&scenario=priceChange". When
            the server does not recognise the value, the call behaves exactly as if no Test header
            had been sent.
          required: false
          example: ""
          schema:
            description: >-
              Test flags. support key-value pairs, eg, "hotel=HC1&scenario=priceChange".If it's not
              recognized by server, the call will behave as if the "Test" header was not provided.
            type: string
        - name: Timeout-Milliseconds
          in: header
          description: >-
            Client-specified timeout. The server makes a best effort to return data before it
            elapses.
          required: false
          example: 0
          schema:
            description: >-
              timeout specified by client, and server will try its best to return data before this
              timeout
            type: integer
            format: int64
        - name: Trace-Id
          in: header
          description: Correlates a group of related requests for tracing.
          required: false
          example: ""
          schema:
            description: for tracing a group of requests
            type: string
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: >-
            Must start with "Bearer ". The token comes from the Ticket response. The Ticket call
            itself does not need this header.
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.trade.protocol.BookReq"
            examples:
              twoAdultsOneRoom:
                summary: Book a rate package for two adults in one room
                description: >-
                  `customerReferenceNo` is your own idempotency key — retrying with the same value
                  returns the original order rather than creating a second one. `Session-Id` is
                  required and must be the session the `ratePkgId` came from.
                value:
                  customerReferenceNo: 9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50
                  ratePkgId: rp_8f3c1a7e6b2d40f9a51c
                  holder:
                    firstName: John
                    lastName: Doe
                    email: john.doe@example.com
                    phone:
                      countryCode: AE
                      countryNumber: 971
                      number: "525757249"
                  guests:
                    - roomIndex: 1
                      firstName: John
                      lastName: Doe
                      nationalityCode: US
                      isChild: false
                    - roomIndex: 1
                      firstName: Jane
                      lastName: Doe
                      nationalityCode: US
                      isChild: false
      responses:
        "200":
          description: >-
            OK. Distinguished by the `code` field: `code` 0 carries the confirmed
            BookRespEnvelope, while `code` 100001111 (ARIChangedErr) is returned —
            still with HTTP 200 — when the rate moved between CheckAvail and this
            commit and can no longer be booked at the quoted terms. Re-shop from
            HotelRates on 100001111.
          headers: {}
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/BookRespEnvelope"
                  - $ref: "#/components/schemas/ARIChangedErr"
              examples:
                ariChanged:
                  summary: ARI changed (rate moved before commit)
                  description: >-
                    RateUnavailableError from the booking engine renders as HTTP 200
                    with business code 100001111.
                  value:
                    code: 100001111
                    msg: ARI changed
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "504":
          description: Upstream or supplier timeout
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TimeoutErr"
  /api/trade/queryOrders:
    post:
      operationId: queryOrders
      summary: QueryOrders
      deprecated: false
      tags:
        - Manage bookings
      description: >-
        Retrieves hotel booking orders using a set of optional filters, and acts as the
        authoritative check on the real state of an order after a Book call.


        The primary operational role of this endpoint is reconciliation. When a Book call times out
        or fails at the network layer, the client has no way of knowing whether the reservation was
        actually created. Polling this endpoint with the customerReferenceNo settles that question
        and avoids duplicate reservations, unreconciled charges, and client/server state drift.


        **Recovering from a Book timeout or network failure**


        Do not immediately re-issue the Book call. Wait for backend processing to finish, then query
        here with the customerReferenceNo that was submitted to Book.


        Processing timing:

        - Book performs backend work after the HTTP call completes.

        - Full completion normally lands within a 3-10 minute window.

        - Back off exponentially between polls so that fast successes are detected quickly while
        slow ones are still given time to settle.


        Suggested polling sequence:

        1. Book returns a timeout or network error.

        2. Poll once immediately. If an order comes back, stop - the booking almost certainly went
        through.

        3. If nothing is returned, wait 30 seconds and poll again.

        4. Still nothing: wait 1 minute, then 2 minutes, doubling each time, up to a 10 minute
        ceiling.

        5. Inspect the status on every response. A confirmed order is treated as a successful
        booking; a pending order means keep polling.

        6. If nothing has materialised after the 10 minute ceiling, re-issuing Book may be
        appropriate.


        Backing off this way gives immediate detection of successful bookings, allows slower ones
        time to complete, keeps client resource use proportionate, and avoids hammering the platform
        with tight-loop queries.


        **Filters**


        Recommended:

        - customerReferenceNos - the customer reference numbers supplied to Book. This is the filter
        to use for timeout recovery.


        Optional:

        - platformReferenceNos - platform-internal reference numbers (see note: not present in the
        request schema)

        - supplierReferenceNos - reference numbers issued by the supplier

        - statusList - restrict to specific order statuses (confirmed, cancelled, pending, and so
        on)

        - checkInTimeWindow - restrict by check-in date range

        - checkOutTimeWindow - restrict by check-out date range

        - bookingTimeWindow - restrict by booking creation date range

        - freeCancelTimeWindow - restrict by free-cancellation date range

        - cancelledTimeWindow - restrict by cancellation date range


        **What comes back**


        Each matching order carries its full detail: current status, booking confirmation data,
        pricing, payment and cancellation detail, and supplier reference numbers.


        **Rate limiting**


        High-volume querying is rate limited and will return HTTP 429. Use the backoff strategy
        above rather than polling aggressively.


        **Typical uses**

        - Verifying order state after a network failure on Book

        - Ongoing order tracking and monitoring

        - Customer-service order lookups

        - Confirming a booking went through

        - Financial reconciliation and audit
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: client request time(start to send request); unix timestamp
          required: false
          example: 0
          schema:
            description: client request time(start to send request); unix timestamp
            type: integer
            format: int64
        - name: IP
          in: header
          description: client IP address, compatible with both IPv4 and IPv6
          required: false
          example: ""
          schema:
            description: client IP address, compatible with both IPv4 and IPv6
            type: string
        - name: Language
          in: header
          description: >-
            IETF BCP 47 language tag (see https://masonreview.com/posts/ietf-bcp-47-language-tags/),
            eg: "en", "en-US"; default "en-US"
          required: false
          example: ""
          schema:
            description: >-
              IETF BCP 47 language tag (see
              https://masonreview.com/posts/ietf-bcp-47-language-tags/), eg: "en", "en-US"; default
              "en-US"
            type: string
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: for identifying the current request, it can't be duplicate
          required: false
          example: ""
          schema:
            description: for identifying the current request, it can't be duplicate
            type: string
        - name: Trace-Id
          in: header
          description: for tracing a group of requests
          required: false
          example: ""
          schema:
            description: for tracing a group of requests
            type: string
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: starts with "Bearer ". got from Ticket response. Ticket doesn't need it
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.trade.protocol.QueryOrdersReq"
            examples:
              timeoutRecoveryByCustomerReference:
                summary: Timeout recovery - look up by customer reference number
                description: >-
                  ASSEMBLED EXAMPLE. The source document contains no whole-body request example;
                  this is composed only from literal values documented at field level.
                value:
                  customerReferenceNos:
                    - "1234567890"
              filteredByStatusAndWindows:
                summary: Filter by status and date windows
                description: >-
                  ASSEMBLED EXAMPLE. Time values use the RFC3339 layout literal documented in the
                  source field examples.
                value:
                  customerReferenceNos:
                    - "1234567890"
                  supplierReferenceNos:
                    - "1234567890"
                  statusList:
                    - 1
                    - 2
                  checkInTimeWindow:
                    start: 2006-01-02T15:04:05Z07:00
                    end: 2006-01-02T15:04:05Z07:00
                  checkOutTimeWindow:
                    start: 2006-01-02T15:04:05Z07:00
                    end: 2006-01-02T15:04:05Z07:00
                  bookingTimeWindow:
                    start: 2006-01-02T15:04:05Z07:00
                    end: 2006-01-02T15:04:05Z07:00
                  freeCancelTimeWindow:
                    start: 2006-01-02T15:04:05Z07:00
                    end: 2006-01-02T15:04:05Z07:00
                  cancelledTimeWindow:
                    start: 2006-01-02T15:04:05Z07:00
                    end: 2006-01-02T15:04:05Z07:00
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/QueryOrdersRespEnvelope"
              examples:
                confirmingOrder:
                  summary: One order still confirming
                  description: >-
                    ASSEMBLED EXAMPLE. The source document has no whole-body response example. Every
                    value below that is documented at field level is reproduced exactly; values
                    marked PLACEHOLDER have no documented example in the source.
                  value:
                    code: 0
                    msg: ok
                    data:
                      orders:
                        - status: 1
                          statusRemark: aborted
                          checkIn: "2026-01-01"
                          checkOut: "2026-01-03"
                          nightCount: 2
                          roomCount: 1
                          bookingTime: "2026-01-01T10:00:00Z"
                          hotelConfirmNo: "123456"
                          holder:
                            email: johndoe@example.com
                            firstName: John
                            lastName: Doe
                            phone:
                              countryCode: "1"
                              number: "1234567890"
                          platformReferenceNo: "1234567890"
                          customerReferenceNo: "1234567890"
                          commissionableRate:
                            amount: 14.5
                            currency: USD
                          netRate:
                            amount: 14.5
                            currency: USD
                          grossRate:
                            amount: 14.5
                            currency: USD
                          respectGrossRate: false
                          supplier: 20000001
                          supplierReferenceNo: SUPPLIER-REF-PLACEHOLDER
                          hotel:
                            hotelId: HOTEL-ID-PLACEHOLDER
                            destinationId: "804028047"
                            name:
                              en: Jumeirah Beach Hotel
                            rating: 4.5
                            address:
                              en: Millenium Al Barsha
                            latlngCoordinator:
                              google:
                                lat: 25.0478
                                lng: 121.5319
                              gaode:
                                lat: 25.0478
                                lng: 121.5319
                            logoURL: https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
                          rooms:
                            - roomTypeId: R001
                              roomTypeName:
                                en: Standard Room
                              hotelId: HOTEL-ID-PLACEHOLDER
                              ratePkgId: RATE-PKG-ID-PLACEHOLDER
                              refundableMode: full
                              refundableUntil: 2006-01-02T15:04:05Z07:00
                              cancelFees:
                                - until: 2006-01-02T15:04:05Z07:00
                                  fee:
                                    amount: 0
                                    currency: USD
                              rate:
                                netRate:
                                  amount: 14.5
                                  currency: USD
                              totalRate:
                                netRate:
                                  amount: 14.5
                                  currency: USD
                              includesPackaging: false
                              checkIn: "2026-01-01"
                              checkOut: "2026-01-03"
                              board:
                                boardId: BB
                              roomIndex: 1
                              guests:
                                - roomIndex: 1
                                  firstName: John2
                                  lastName: Doe
                                  nationalityCode: US
                                  age: 18
                                  isChild: false
                cancelledOrder:
                  summary: One cancelled and refunded order
                  description: >-
                    ASSEMBLED EXAMPLE. Reproduces the cancellation-related field examples documented
                    in the source (cancelTime, cancelReason, refundedPrice).
                  value:
                    code: 0
                    msg: ok
                    data:
                      orders:
                        - status: 3
                          checkIn: "2026-01-01"
                          checkOut: "2026-01-03"
                          bookingTime: "2026-01-01T10:00:00Z"
                          cancelTime: "2026-01-02T10:00:00Z"
                          cancelReason: Customer requested cancellation
                          refundedPrice:
                            amount: 99
                            currency: USD
                          platformReferenceNo: "1234567890"
                          customerReferenceNo: "1234567890"
                          supplier: 20000001
                          rooms:
                            - roomTypeId: R001
                              roomTypeName:
                                en: Standard Room
                              hotelId: HOTEL-ID-PLACEHOLDER
                              ratePkgId: RATE-PKG-ID-PLACEHOLDER
                              refundableMode: "no"
                              checkIn: "2026-01-01"
                              checkOut: "2026-01-03"
                              rate:
                                netRate:
                                  amount: 14.5
                                  currency: USD
                              totalRate:
                                netRate:
                                  amount: 14.5
                                  currency: USD
                              refundInfo:
                                - date: "2026-01-01"
                                  refunded: true
                                  refundedMoney:
                                    amount: 99
                                    currency: USD
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Too many requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RateLimitErr"
              examples:
                quotaExceeded:
                  summary: Quota limit exceeded
                  value:
                    code: 100000429
                    msg: quota limit exceed
  /api/trade/orderVoucher:
    post:
      operationId: orderVoucher
      summary: OrderVoucher
      deprecated: false
      tags:
        - Manage bookings
      description: |-
        Retrieves the hotel voucher for an order you placed — the travel document your
        guest presents at the hotel desk.

        The voucher is produced by the platform when the supplier confirms the booking, so
        it is not available the instant Book returns. This endpoint always reports a
        `status`; the `voucher` block is present only when that status is `GENERATED`.
        A booking that is genuinely yours but whose voucher has not been issued yet is a
        `200` with `status: NOT_GENERATED`, not an error — poll it the same way you poll
        QueryOrders.

        **Identifying the order**

        Supply at least one of `customerReferenceNo` (your own reference, sent on Book),
        `platformReferenceNo` (our order number) or `supplierReferenceNo`. If a reference
        matches more than one order the call is refused with `100001008` rather than
        guessing — supply `platformReferenceNo`, which is unique.

        **Getting the bytes**

        `voucher.downloadUrl` is a time-limited object URL; `voucher.expiresIn` is how many
        seconds it remains valid. Set `includeDocument: true` to receive the PDF inline as
        base64 in `voucher.content` instead of following the link — intended for
        integrations that cannot reach an object-storage URL from where they run. Documents
        above 8 MB are never inlined; that request is refused with `100001005`.

        **Checking the document is the one we issued**

        Every voucher is signed at the moment it is rendered. `voucher.signature.digest` is
        the SHA-256 of the exact bytes we issued, in lowercase hex. Hash whatever you
        received and compare — if the two differ, the file has been altered since issue and
        must not be given to a traveller. `signature.signature` is a detached HMAC only we
        can verify; it is returned so the claim is auditable, not so you can check it
        yourself. A voucher rendered before document signing was introduced has no
        `signature` block at all, rather than a fabricated one.

        `voucher.verifyUrl` is the same public verification page the voucher's QR code
        opens, which reports whether the document is still valid and whether it is
        unaltered.

        **Access**

        The calling key must be scoped `booking:read`, and the order must belong to you. An
        order that is not yours answers `100000404 not found` — the same answer as a
        reference that never existed, so the endpoint cannot be used to probe another
        seller's order book.

        **Status values**

        - `GENERATED` — issued and current; `voucher` is present.
        - `NOT_GENERATED` — no voucher has been issued for this order yet.
        - `PENDING` — a voucher number is reserved and the document is being produced.
        - `FAILED` — generation was attempted and did not complete; contact support.
        - `CANCELLED` — the booking is cancelled. The document is deliberately withheld:
          a reissued voucher for a cancelled stay is stamped "not valid for check-in" and
          must not be handed to a traveller by an automated pipeline.
      parameters:
        - $ref: "#/components/parameters/ClientRequestTimestamp"
        - $ref: "#/components/parameters/IP"
        - $ref: "#/components/parameters/Language"
        - $ref: "#/components/parameters/Market"
        - $ref: "#/components/parameters/RequestId"
        - $ref: "#/components/parameters/TraceId"
        - $ref: "#/components/parameters/UserRef"
        - $ref: "#/components/parameters/Authorization"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.trade.protocol.OrderVoucherReq"
            examples:
              byCustomerReference:
                summary: Fetch a voucher by your own reference
                value:
                  customerReferenceNo: 9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50
              inlineDocument:
                summary: Fetch the PDF inline, base64-encoded
                description: >-
                  For integrations that cannot follow a presigned object URL. `content.base64`
                  is the same bytes `downloadUrl` would serve.
                value:
                  platformReferenceNo: TTD-2026-000042
                  includeDocument: true
      responses:
        "200":
          description: OK
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderVoucherRespEnvelope"
              examples:
                issued:
                  summary: Voucher issued
                  value:
                    code: 0
                    msg: success
                    data:
                      customerReferenceNo: 9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50
                      platformReferenceNo: TTD-2026-000042
                      supplierReferenceNo: JP046300-778812
                      status: GENERATED
                      voucher:
                        voucherNumber: VCH-TTD-2026-000042-01
                        version: 1
                        issuedAt: "2026-07-20T09:00:00.000Z"
                        contentType: application/pdf
                        byteSize: 184320
                        verifyUrl: >-
                          https://portal.ttdbooking.com/voucher/verify/VCH-TTD-2026-000042-01?t=3f9a1c7e5b2d8460a1c3e5f70921b4d6
                        downloadUrl: https://objects.ttdbooking.com/pdfs/...?X-Amz-Signature=...
                        expiresIn: 3600
                        signature:
                          alg: HMAC-SHA256
                          keyId: ttd-derived-v1
                          digest: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
                          signature: 6c1f5d3e0a7b48c29d3f81e64b2a0c7d5e9f13a8b4c6d2e0f7a9b1c3d5e7f9a1
                          signedAt: "2026-07-20T09:00:00.000Z"
                notIssuedYet:
                  summary: Order is yours, voucher not issued yet
                  description: >-
                    A 200, not an error. Poll until `status` becomes `GENERATED`, the same way
                    you poll QueryOrders after a Book timeout.
                  value:
                    code: 0
                    msg: success
                    data:
                      customerReferenceNo: 9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50
                      platformReferenceNo: TTD-2026-000042
                      status: NOT_GENERATED
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden — this key is not scoped for booking:read
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Order not found, or not yours
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundErr"
              examples:
                notFound:
                  summary: Order not found
                  value:
                    code: 100000404
                    msg: not found
          headers: {}
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/trade/cancel:
    post:
      operationId: cancel
      summary: Cancel
      description: |
        Cancels a hotel booking order, validating order state and recording an
        audit trail as the cancellation is processed.

        Both full and partial cancellation are supported; which one applies is
        determined by supplier policy and by the current state of the order.

        **Critical Prerequisites:**
        - **Order ID**: Must be provided to identify the target order
        - **JWT Authentication**: Bearer token required in Authorization header
        - **Valid Order State**: Order must be in a cancellable state

        **Cancellation Types:**
        - **Full Cancellation**: Complete order cancellation (most common)
        - **Partial Cancellation**: Cancel specific nights or rooms (supplier-dependent)
        - **State-Dependent**: Cancellation rules vary by order status and supplier policies

        **Enterprise Reliability Features:**
        - Order state machine validation and transitions
        - Comprehensive audit logging and tracking
        - Automatic rollback on processing failures
        - CQRS event publishing for downstream processing
        - Processing time monitoring and performance tracking

        **State Validation:**
        - Validates order exists and is accessible
        - Checks current order state for cancellation eligibility
        - Prevents cancellation of non-cancellable orders
        - Returns appropriate validation errors for invalid states

        **Processing Flow:**
        1. Validate order existence and accessibility
        2. Check order state for cancellation eligibility
        3. Update order state to NeedCancel
        4. Publish cancellation event to CQRS queue
        5. Handle rollback if processing fails
        6. Record comprehensive audit logs

        **Error Handling:**
        - Order not found errors with appropriate HTTP status
        - State validation errors for non-cancellable orders
        - Downstream timeout errors for supplier delays
        - Automatic rollback on critical processing failures

        **Common Use Cases:**
        - Customer-initiated order cancellations
        - Administrative order cancellations
        - Policy-based cancellation processing
        - Order lifecycle management
      deprecated: false
      tags:
        - Manage bookings
      parameters:
        - name: Client-Request-Timestamp
          in: header
          description: client request time(start to send request); unix timestamp
          required: false
          example: 0
          schema:
            description: client request time(start to send request); unix timestamp
            type: integer
            format: int64
        - name: Currency
          in: header
          description: Requested currency for the rates, in https://en.wikipedia.org/wiki/ISO_4217 format
          required: false
          example: ""
          schema:
            description: Requested currency for the rates, in https://en.wikipedia.org/wiki/ISO_4217 format
            type: string
        - name: IP
          in: header
          description: client IP address, compatible with both IPv4 and IPv6
          required: false
          example: ""
          schema:
            description: client IP address, compatible with both IPv4 and IPv6
            type: string
        - name: Language
          in: header
          description: >-
            https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
            "en-US"
          required: false
          example: ""
          schema:
            description: >-
              https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default
              "en-US"
            type: string
        - name: Market
          in: header
          description: >-
            Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
            your account carries a market restriction: an allow-list cannot admit a market you have not
            stated, so such an account refuses calls that omit it.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
              your account carries a market restriction: an allow-list cannot admit a market you have not
              stated, so such an account refuses calls that omit it.
        - name: Request-Id
          in: header
          description: for identifying the current request, it can't be duplicate
          required: false
          example: ""
          schema:
            description: for identifying the current request, it can't be duplicate
            type: string
        - name: Session-Id
          in: header
          description: Suggested provided in request by client. It's required in booking flow.
          required: true
          example: ""
          schema:
            description: Suggested provided in request by client. It's required in booking flow.
            type: string
        - name: Test
          in: header
          description: >-
            Test flags. support key-value pairs, eg, "hotel=HC1&scenario=priceChange".If it's not
            recognized by server, the call will behave as if the "Test" header was not provided.
          required: false
          example: ""
          schema:
            description: >-
              Test flags. support key-value pairs, eg, "hotel=HC1&scenario=priceChange".If it's not
              recognized by server, the call will behave as if the "Test" header was not provided.
            type: string
        - name: Timeout-Milliseconds
          in: header
          description: >-
            timeout specified by client, and server will try its best to return data before this
            timeout
          required: false
          example: 0
          schema:
            description: >-
              timeout specified by client, and server will try its best to return data before this
              timeout
            type: integer
            format: int64
        - name: Trace-Id
          in: header
          description: for tracing a group of requests
          required: false
          example: ""
          schema:
            description: for tracing a group of requests
            type: string
        - name: User-Ref
          in: header
          description: >-
            Your own identifier for the person on whose behalf this call is made. Required only once named
            users have been authorised on your account, after which every call must identify one and is
            authorised against that user's scopes as well as the key's.
          required: false
          example: ""
          schema:
            type: string
            description: >-
              Your own identifier for the person on whose behalf this call is made. Required only once named
              users have been authorised on your account, after which every call must identify one and is
              authorised against that user's scopes as well as the key's.
        - name: Authorization
          in: header
          required: true
          description: starts with "Bearer ". got from Ticket response. Ticket doesn't need it
          example: Bearer {{token}}
          schema:
            type: string
            default: Bearer {{token}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/hotel.trade.protocol.CancelReq"
            examples:
              byBothReferences:
                summary: Cancel an existing order
                description: >-
                  Both reference numbers are required — yours from the book request, and the
                  supplier's from the book response. `Session-Id` is required on this endpoint.
                value:
                  customerReferenceNo: 9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50
                  supplierReferenceNo: TTD-2609-004871
                  reason: Guest cancelled within the free-cancellation window
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CancelRespEnvelope"
          headers: {}
        "400":
          description: Bad Request
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "401":
          description: Unauthorized
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "403":
          description: Forbidden
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Order not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundErr"
              examples:
                notFound:
                  summary: Order not found
                  value:
                    code: 100000404
                    msg: not found
          headers: {}
        "429":
          description: Too Many Requests
          headers: {}
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "504":
          description: Downstream supplier timeout
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TimeoutErr"
              examples:
                downstreamTimeout:
                  summary: Downstream supplier timeout
                  value:
                    code: 100000504
                    msg: timeout
          headers: {}
webhooks:
  orderStatusCallback:
    post:
      operationId: orderStatusCallback
      summary: Order status callback
      description: |-
        Sent to the `callbackUrl` supplied on Book whenever the order's status changes,
        so you do not have to poll QueryOrders.

        Deliveries are signed. `X-TTD-Signature` carries `t=<unix seconds>` and
        `v1=<hex>`, where `v1` is the HMAC-SHA256 of `"{t}.{rawBody}"` keyed with your
        webhook signing secret. Verify against the raw bytes, before parsing.

        Return any 2xx to acknowledge. Non-2xx and timeouts are retried with
        exponential backoff, so handlers must be idempotent — key on
        `X-TTD-Event-Id`, or on `customerReferenceNo` plus `event`.
      parameters:
        - name: X-TTD-Signature
          in: header
          required: true
          description: '`t=<unix seconds>,v1=<hmac-sha256 hex>` over `"{t}.{rawBody}"`.'
          schema:
            type: string
          example: t=1704067200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
        - name: X-TTD-Event-Id
          in: header
          required: true
          description: Stable id for this event; use it for idempotency.
          schema:
            type: string
          example: evt_01HQ8Z3K9M2N4P6R8T0V2X4Y6A
        - name: User-Agent
          in: header
          required: false
          description: Always `ttdbooking-webhook/1.0`.
          schema:
            type: string
            const: ttdbooking-webhook/1.0
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrderStatusCallback"
      responses:
        "200":
          description: Acknowledged. Any 2xx is treated as success.
components:
  securitySchemes:
    ticketAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "The ticket returned by `POST /api/auth/ticket`, sent as `Authorization: Bearer <ticket>`."
    oauth2ClientCredentials:
      type: oauth2
      description: >-
        An OAuth 2.0 client-credentials access token (RFC 6749 §4.4), sent as
        `Authorization: Bearer <access_token>` on the same endpoints the ticket
        serves. Register a client with your account manager to obtain a
        `client_id` and `client_secret`; the token is opaque, is revocable at
        any time, and expires after the lifetime configured on the client (one
        hour by default). Unlike a ticket — where an empty scope list means full
        access for historical reasons — a token must carry the scope for each
        operation it calls, and a token with no scopes is refused.
      flows:
        clientCredentials:
          tokenUrl: /api/v1/oauth/token
          scopes:
            search:read: Availability and rate discovery (hotelList, hotelRates, checkAvail)
            content:read: Static content (destinations, hotelStaticDetail, hotelsMetadata)
            booking:read: Read orders and vouchers (queryOrders, orderVoucher)
            booking:write: Create bookings (book)
            booking:cancel: Cancel bookings (cancel)
  parameters:
    ClientRequestTimestamp:
      name: Client-Request-Timestamp
      in: header
      description: Client-side send time for this request, expressed as a unix timestamp.
      required: false
      example: 0
      schema:
        description: Client-side send time for this request, expressed as a unix timestamp.
        type: integer
        format: int64
    IP:
      name: IP
      in: header
      description: Caller IP address; both IPv4 and IPv6 are accepted.
      required: false
      example: ""
      schema:
        description: Caller IP address; both IPv4 and IPv6 are accepted.
        type: string
    Language:
      name: Language
      in: header
      description: >-
        IETF BCP 47 language tag (see https://masonreview.com/posts/ietf-bcp-47-language-tags/), for
        example "en" or "en-US". Falls back to "en-US" when omitted.
      required: false
      example: ""
      schema:
        description: >-
          IETF BCP 47 language tag (see https://masonreview.com/posts/ietf-bcp-47-language-tags/),
          for example "en" or "en-US". Falls back to "en-US" when omitted.
        type: string
    RequestId:
      name: Request-Id
      in: header
      description: Identifier for this individual request; values must not repeat.
      required: false
      example: ""
      schema:
        description: Identifier for this individual request; values must not repeat.
        type: string
    TraceId:
      name: Trace-Id
      in: header
      description: Identifier used to correlate a group of related requests.
      required: false
      example: ""
      schema:
        description: Identifier used to correlate a group of related requests.
        type: string
    Market:
      name: Market
      in: header
      description: >-
        Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
        your account carries a market restriction: an allow-list cannot admit a market you have not
        stated, so such an account refuses calls that omit it.
      required: false
      example: ""
      schema:
        description: >-
          Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when
          your account carries a market restriction: an allow-list cannot admit a market you have not
          stated, so such an account refuses calls that omit it.
        type: string
    UserRef:
      name: User-Ref
      in: header
      description: >-
        Your own identifier for the person on whose behalf this call is made. Required only once named
        users have been authorised on your account, after which every call must identify one and is
        authorised against that user's scopes as well as the key's.
      required: false
      example: ""
      schema:
        description: >-
          Your own identifier for the person on whose behalf this call is made. Required only once named
          users have been authorised on your account, after which every call must identify one and is
          authorised against that user's scopes as well as the key's.
        type: string
    Authorization:
      name: Authorization
      in: header
      required: true
      description: >-
        Bearer credential — the value must be prefixed with "Bearer ". Obtain the token from the
        Ticket response. The Ticket call itself does not require this header.
      example: Bearer {{token}}
      schema:
        type: string
        default: Bearer {{token}}
  schemas:
    hotel.api.protocol.TicketReq:
      title: TicketReq
      type: object
      properties:
        appKey:
          type: string
          description: The application key used to obtain this ticket.
          examples:
            - ttdbooking_api_demo
        appSecret:
          type: string
          description: The application secret used to obtain this ticket.
          examples:
            - ttdbooking_api_demo
        ttl:
          type: integer
          format: int64
          description: >-
            Total lifetime of this ticket, expressed as an integer number of seconds and counted
            from issuance. It is NOT an idle timeout: expiry is absolute and is not extended by API
            activity. When omitted the server applies a 24-hour (86400) default. Must be positive
            and no greater than 365 days (31536000). The source schema declares no `default`,
            `minimum` or `maximum`; those bounds are enforced by this implementation.
          examples:
            - 3600
      required:
        - appKey
        - appSecret
    hotel.api.protocol.TicketResp:
      title: TicketResp
      type: object
      properties:
        ticket:
          type: string
          description: The generated ticket value.
      required:
        - ticket
    TicketRespEnvelope:
      title: TicketResp
      type: object
      properties:
        code:
          type: integer
          description: >-
            Result code for the call. The source supplies no enumeration, success value or
            description for this field.
        msg:
          type: string
          description: >-
            Result message for the call. The source supplies no description or example for this
            field.
        data:
          $ref: "#/components/schemas/hotel.api.protocol.TicketResp"
      x-display-name: hotel.api.protocol.TicketResp
      x-primary-property: data
    hotel.search.protocol.DestinationsReq:
      title: DestinationsReq
      type: object
      description: >-
        Request body for the destinations lookup. Property order follows the source
        `x-apifox-orders`.
      properties:
        countryCode:
          type: string
          description: The country code, for example "US".
          examples:
            - AE
        parentDestinationId:
          title: ID
          type: string
          description: >-
            Unique identifier of the ancestor destination. This field is disregarded when a country
            code is supplied.
          examples:
            - "804028047"
        include:
          title: DestinationInclude
          type: string
          description: >-
            Selects how much detail the response carries. Permitted values are "standard" and
            "details"; "standard" is used when the field is omitted.
          enum:
            - standard
            - details
          x-enum-descriptions:
            standard: Return the metadata and basic hierarchy of each region.
            details: Return the metadata, coordinates and full hierarchy of each region.
          x-enum-varnames:
            - DestinationInclude_Standard
            - DestinationInclude_Details
        filterEmptyCities:
          type: boolean
          description: Drop cities that have no hotels. Treated as true when the field is omitted.
        minHotelCount:
          type: integer
          description: >-
            Lowest hotel count a city must reach to be returned. Treated as 1 when the field is
            omitted.
    DestinationsRespEnvelope:
      title: DestinationsResp
      type: object
      description: Standard response wrapper. The meaningful payload sits on `data`.
      x-display-name: hotel.search.protocol.DestinationsResp
      x-primary-property: data
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.search.protocol.DestinationsResp"
    hotel.search.protocol.DestinationsResp:
      title: DestinationsResp
      type: object
      properties:
        destinations:
          type: array
          description: Carries the region records.
          items:
            $ref: "#/components/schemas/Destination"
    Destination:
      title: Destination
      type: object
      description: Carries the region records.
      properties:
        id:
          title: ID
          type: string
        type:
          $ref: "#/components/schemas/hotel.geography.domain.DestinationType"
        name:
          $ref: "#/components/schemas/I18N"
          description: Localised name.
        nameFull:
          $ref: "#/components/schemas/I18N"
          description: >-
            Fully qualified localised name, for example "Springfield, Missouri, United States of
            America".
        countryCode:
          type: string
          description: "ISO 3166-1 alpha-2 country code. Reference: https://www.iso.org/obp/ui/#search"
        coordinates:
          $ref: "#/components/schemas/Coordinates"
        extra:
          $ref: "#/components/schemas/hotel.geography.domain.DestinationExtra"
        countryName:
          $ref: "#/components/schemas/I18N"
        destinationName:
          $ref: "#/components/schemas/I18N"
        parentDestinationName:
          $ref: "#/components/schemas/I18N"
        parentDestinationId:
          type: string
          description: >-
            Code of the parent region: for a city this is the province code, for a province it is
            the country code.
    Coordinates:
      title: Coordinates
      type: object
      description: Location descriptor.
      properties:
        centerLat:
          type: number
        centerLng:
          type: number
        boundingPolygon:
          $ref: "#/components/schemas/BoundingPolygon"
    BoundingPolygon:
      title: BoundingPolygon
      type: object
      properties:
        type:
          type: string
          description: Polygon,...
        coordinates:
          type: array
          items:
            $ref: "#/components/schemas/Latlng"
    Latlng:
      title: Latlng
      type: object
      properties:
        lat:
          type: number
        lng:
          type: number
    hotel.geography.domain.DestinationExtra:
      title: DestinationExtra
      type: object
      properties:
        cityName:
          $ref: "#/components/schemas/I18N"
          description: City name.
        provinceName:
          $ref: "#/components/schemas/I18N"
          description: Province name.
        continentName:
          $ref: "#/components/schemas/I18N"
          description: Continent name.
        hotelCount:
          description: Hotel count.
          type: integer
          format: int64
    I18N:
      title: I18N
      type: object
      description: Localised string set. Keys are fixed language codes.
      properties:
        en:
          type: string
          description: English; the default system language.
        zh:
          type: string
          description: Chinese (中文).
        ar:
          type: string
          description: Arabic (اللغة العربية).
    hotel.geography.domain.DestinationType:
      title: DestinationType
      type: integer
      description: >
        Classification of a destination record.


        - `DestinationType_Unknown` (`0`): no description supplied in the source.


        - `DestinationType_Continent` (`1`): a large landmass such as Europe, Asia or South America.
        The region summary section lists the continents.


        - `DestinationType_Country` (`2`): a nation-state such as the United States, Australia or
        Germany. Countries/regions here are drawn geographically rather than politically -
        Guadeloupe, for instance, is a French department in the Caribbean that belongs politically
        to France yet forms its own geographic entity. The region summary section lists the
        countries/regions.


        - `DestinationType_ProvinceState` (`3`): an administrative division inside a country, such
        as California or New South Wales. Lower-level administrative divisions - counties and
        provinces within a country/region - fall under this type too.


        - `DestinationType_HighLevelRegion` (`4`): a tourist region, such as the Upper Rhine in
        Germany or the wine country in California.


        - `DestinationType_MultiCityVicinity` (`5`): a large metropolitan area covering a major city
        together with its surrounding suburbs, such as Cairo and the areas around it. Polygon
        boundaries for these are drawn broadly according to tourist value.


        - `DestinationType_City` (`6`): an urban area, such as Bellevue and Washington. A large
        metropolitan area can contain a city - London, for example - in which case the city covers a
        smaller footprint than the corresponding multi_city_vicinity. Each accommodation contracted
        with Expedia must be tied to a city, since the city is the base unit of geographic coverage.
        City polygon boundaries follow official administrative sources.


        - `DestinationType_Neighborhood` (`7`): a geographic area smaller than a city, such as the
        old town in Bonn, Germany. Neighborhood polygon boundaries are drawn by tourist value rather
        than by administrative definition.


        - `DestinationType_Airport` (`8`): an airport, such as LHR (London Heathrow).


        - `DestinationType_PointOfInterest` (`9`): a place such as a museum, convention center,
        beach or park. The list covers not only well-known tourist attractions but a broader set of
        venues, such as the Shanghai Exhibition Center, the Texas State Capitol or the Prague Zoo.


        - `DestinationType_TrainStation` (`10`): a train station, such as Grand Central Terminal in
        New York.


        - `DestinationType_MetroStation` (`11`): a subway station, such as Avtovo Station in St.
        Petersburg, Russia.


        - `DestinationType_BusStation` (`12`): a bus station, such as the Port Authority Bus
        Terminal in New York State, USA.
      enum:
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        - 10
        - 11
        - 12
      x-enum-varnames:
        - DestinationType_Unknown
        - DestinationType_Continent
        - DestinationType_Country
        - DestinationType_ProvinceState
        - DestinationType_HighLevelRegion
        - DestinationType_MultiCityVicinity
        - DestinationType_City
        - DestinationType_Neighborhood
        - DestinationType_Airport
        - DestinationType_PointOfInterest
        - DestinationType_TrainStation
        - DestinationType_MetroStation
        - DestinationType_BusStation
      x-enum-descriptions:
        "0": DestinationType_Unknown - no description supplied in the source.
        "1": >-
          DestinationType_Continent - a large landmass such as Europe, Asia or South America. The
          region summary section lists the continents.
        "2": >-
          DestinationType_Country - a nation-state such as the United States, Australia or Germany.
          Countries/regions are drawn geographically rather than politically; Guadeloupe, for
          instance, is a French department in the Caribbean that belongs politically to France yet
          forms its own geographic entity. The region summary section lists the countries/regions.
        "3": >-
          DestinationType_ProvinceState - an administrative division inside a country, such as
          California or New South Wales; also covers lower-level administrative divisions such as
          counties and provinces within a country/region.
        "4": >-
          DestinationType_HighLevelRegion - a tourist region, such as the Upper Rhine in Germany or
          the wine country in California.
        "5": >-
          DestinationType_MultiCityVicinity - a large metropolitan area covering a major city and
          its surrounding suburbs, such as Cairo and the areas around it. Polygon boundaries are
          drawn broadly according to tourist value.
        "6": >-
          DestinationType_City - an urban area, such as Bellevue and Washington. A large
          metropolitan area can contain a city (London, for example), in which case the city covers
          a smaller footprint than the corresponding multi_city_vicinity. Each accommodation
          contracted with Expedia must be tied to a city, the base unit of geographic coverage. City
          polygon boundaries follow official administrative sources.
        "7": >-
          DestinationType_Neighborhood - a geographic area smaller than a city, such as the old town
          in Bonn, Germany. Polygon boundaries are drawn by tourist value, not by administrative
          definition.
        "8": DestinationType_Airport - an airport, such as LHR (London Heathrow).
        "9": >-
          DestinationType_PointOfInterest - a place such as a museum, convention center, beach or
          park; covers not only well-known attractions but a broader set of venues, such as the
          Shanghai Exhibition Center, the Texas State Capitol or the Prague Zoo.
        "10": >-
          DestinationType_TrainStation - a train station, such as Grand Central Terminal in New
          York.
        "11": >-
          DestinationType_MetroStation - a subway station, such as Avtovo Station in St. Petersburg,
          Russia.
        "12": >-
          DestinationType_BusStation - a bus station, such as the Port Authority Bus Terminal in New
          York State, USA.
    hotel.search.protocol.HotelStaticDetailReq:
      title: HotelStaticDetailReq
      type: object
      properties:
        hotelId:
          title: ID
          type: string
          examples:
            - "461850557"
      required:
        - hotelId
    HotelStaticDetailRespEnvelope:
      title: HotelStaticDetailResp
      type: object
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.search.protocol.HotelStaticDetailResp"
      x-display-name: hotel.search.protocol.HotelStaticDetailResp
      x-primary-property: data
    hotel.search.protocol.HotelStaticDetailResp:
      title: HotelStaticDetailResp
      type: object
      properties:
        hotel:
          $ref: "#/components/schemas/Hotel"
    Hotel:
      title: Hotel
      type: object
      properties:
        id:
          title: ID
          type: string
          examples:
            - "461850557"
        destinationId:
          title: ID
          description: index
          type: string
          examples:
            - "804028047"
        name:
          $ref: "#/components/schemas/I18N"
          description: Hotel name.
          examples:
            - en: Jumeirah Beach Hotel
        rating:
          description: >-
            Hotel rating, on a scale from 0.0 to 5.0. (The range is documented in prose only; the
            source declares no minimum/maximum keywords.)
          type: number
          examples:
            - 4.5
        address:
          $ref: "#/components/schemas/I18N"
          examples:
            - en: Millenium Al Barsha
        latlngCoordinator:
          $ref: "#/components/schemas/LatlngCoordinator"
        logoURL:
          type: string
          examples:
            - https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
        minPrice:
          $ref: "#/components/schemas/Money"
          description: The lowest price satisfying the search criteria.
          examples:
            - amount: 100
              currency: USD
        minPricesByCurrency:
          description: Lowest prices expressed in a range of currencies.
          type: array
          items:
            $ref: "#/components/schemas/Money"
          examples:
            - - amount: 700
                currency: CNY
              - amount: 85
                currency: EUR
        isAvailable:
          type: boolean
          examples:
            - true
        rooms:
          title: RoomList
          type: array
          items:
            $ref: "#/components/schemas/Room"
    Money:
      title: Money
      type: object
      properties:
        currency:
          description: Currency code, e.g. "USD".
          type: string
        amount:
          description: Monetary amount, e.g. "14.50".
          type: number
      required:
        - amount
        - currency
    LatlngCoordinator:
      title: LatlngCoordinator
      type: object
      properties:
        google:
          $ref: "#/components/schemas/Latlng"
        gaode:
          $ref: "#/components/schemas/Latlng"
      required:
        - google
    Room:
      title: Room
      type: object
      properties:
        roomTypeId:
          description: Standardized room type ID, e.g. "R001".
          type: string
        roomTypeName:
          $ref: "#/components/schemas/I18N"
          description: >-
            Standardized room type name. When the supplier's type cannot be recognised, a fallback
            such as "Standard Room" is returned.
        hotelId:
          title: ID
          description: Hotel ID. Repeats the parent hotel's ID so the room can be identified on its own.
          type: string
        rates:
          title: RoomRatePkgList
          description: The core structure — the room offers available for this room.
          type: array
          items:
            $ref: "#/components/schemas/hotel.supplier.domain.RoomRatePkg"
            title: RoomRatePkg
            description: The core structure — the room offers available for this room.
      required:
        - hotelId
        - roomTypeId
        - roomTypeName
    hotel.supplier.domain.RoomRatePkg:
      title: RoomRatePkg
      type: object
      required:
        - checkIn
        - checkOut
        - rate
        - ratePkgId
        - refundableMode
        - totalRate
      properties:
        ratePkgId:
          description: used as key input for checkAvail & book APIs
          title: RatePkgId
          type: string
        refundableMode:
          $ref: "#/components/schemas/RefundableMode"
        refundableUntil:
          description: RefundableMode is valid until RefundableUntil
          type: string
          format: RFC3339 format
          examples:
            - 2006-01-02T15:04:05Z07:00
        cancelFees:
          $ref: "#/components/schemas/hotel.supplier.domain.CancelFees"
        originalRoomNaming:
          $ref: "#/components/schemas/OriginalRoomNaming"
          description: origin room naming fields from supplier
        rate:
          $ref: "#/components/schemas/Rate"
          description: single room price for multiple nights
        totalRate:
          $ref: "#/components/schemas/Rate"
          description: total price for multiple rooms (and multiple nights)
        rateComment:
          type: string
        includesPackaging:
          description: Whether this is a packaged product (e.g., flight+hotel combo)
          type: boolean
        checkIn:
          title: DateInt
          type: string
          default: now()
          description: CheckIn is the check-in date, defaults to current date
          examples:
            - "2026-01-01"
        checkOut:
          title: DateInt
          type: string
          default: now()+7
          description: CheckOut is the check-out date, defaults to 7 days from now
          examples:
            - "2026-01-03"
        board:
          $ref: "#/components/schemas/Board"
          description: Board info - Standard meal plan following liteapi standard
        tax:
          $ref: "#/components/schemas/Tax"
          description: >-
            Taxes and fees, generally collected by hotels on behalf of the government, are fixed
            costs and do not participate in the price increase during the distribution process.
            Therefore, they are listed separately.
    OriginalRoomNaming:
      title: OriginalRoomNaming
      description: Room naming fields exactly as received from the supplier.
      type: object
      properties:
        id:
          description: Unique identifier — the supplier's room code.
          type: string
        name:
          description: Room name as provided by the supplier.
          type: string
        supplier:
          title: Supplier
          description: Supplier identifier.
          type: integer
    Rate:
      title: Rate
      type: object
      properties:
        commissionableRate:
          $ref: "#/components/schemas/Money"
          description: Basis used when calculating commission.
        netRate:
          $ref: "#/components/schemas/Money"
        grossRate:
          $ref: "#/components/schemas/Money"
        respectGrossRate:
          description: >-
            When true, honour grossRate. Documented default is false, though the source supplies no
            schema-level `default` keyword.
          type: boolean
      required:
        - netRate
    Board:
      title: Board
      type: object
      description: Board info - Standard meal plan following liteapi standard
      required:
        - boardId
      properties:
        boardId:
          $ref: "#/components/schemas/BoardId"
          description: BoardId is the meal plan code (standard enum)
        boardName:
          $ref: "#/components/schemas/I18N"
          description: BoardName is the meal plan name (multilingual)
        boardDesc:
          $ref: "#/components/schemas/I18N"
          description: BoardDesc is the meal plan description (multilingual)
    Tax:
      title: Tax
      type: object
      description: >-
        Taxes and fees. These are typically collected by the hotel on the government's behalf;
        because they are fixed costs and are not marked up as the rate moves through distribution,
        they are itemised separately.
      properties:
        total:
          $ref: "#/components/schemas/Money"
        items:
          type: array
          items:
            $ref: "#/components/schemas/TaxItem"
    TaxItem:
      title: TaxItem
      type: object
      properties:
        taxType:
          description: Tax category, e.g. VAT, SERVICE_CHARGE, CITY_TAX.
          type: string
        taxName:
          type: string
        amount:
          $ref: "#/components/schemas/Money"
        desc:
          type: string
    hotel.supplier.domain.CancelFees:
      title: CancelFees
      type: array
      items:
        $ref: "#/components/schemas/hotel.supplier.domain.ComputedCancelPolicyItem"
    hotel.supplier.domain.ComputedCancelPolicyItem:
      title: ComputedCancelPolicyItem
      type: object
      properties:
        until:
          description: Deadline for cancelling under this policy step.
          format: RFC3339 format
          type: string
          examples:
            - 2006-01-02T15:04:05Z07:00
        fee:
          $ref: "#/components/schemas/Money"
          description: Cancellation charge; a value of 0 means cancellation is free.
    hotel.search.protocol.HotelsMetadataReq:
      title: HotelsMetadataReq
      type: object
      required:
        - destinationId
      properties:
        destinationId:
          title: ID
          type: string
          description: Unique identifier of the destination (region) to list hotels for.
          examples:
            - "804028047"
        countryCode:
          type: string
          description: Country code associated with this listing.
          examples:
            - AE
        page:
          $ref: "#/components/schemas/PageReq"
    PageReq:
      title: PageReq
      type: object
      description: >-
        Pagination parameters for the request. The default page size differs by
        endpoint — HotelsMetadata returns 20 per page when `pageSize` is omitted,
        QueryOrders returns 100 — so send it explicitly if the size matters to you.
      properties:
        pageNum:
          type: integer
          format: int64
          default: 1
          description: >-
            Page number to retrieve. The first page is 1; a value below 1 is treated
            as 1 rather than rejected.
          examples:
            - 1
        pageSize:
          type: integer
          format: int64
          default: 20
          description: >-
            Number of items per page, up to 100. A larger value is rejected with code
            100000400. Defaults to 20 on HotelsMetadata and 100 on QueryOrders.
          minimum: 1
          maximum: 100
          examples:
            - 20
        cursor:
          type: integer
          format: int64
          default: 0
          description: Cursor pointing at the next page.
          examples:
            - 0
    HotelsMetadataListRespEnvelope:
      title: HotelsMetadataListResp
      type: object
      description: Standard response envelope wrapping the hotel metadata payload.
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.search.protocol.HotelsMetadataListResp"
      x-display-name: hotel.content.protocol.HotelsMetadataListResp
      x-primary-property: data
    hotel.search.protocol.HotelsMetadataListResp:
      title: HotelsMetadataListResp
      type: object
      properties:
        hotelsMetadata:
          type: array
          description: List of hotel metadata entries.
          items:
            $ref: "#/components/schemas/HotelMeta"
        page:
          $ref: "#/components/schemas/PageResp"
    HotelMeta:
      title: HotelMeta
      type: object
      description: Metadata for a single hotel.
      properties:
        hotelId:
          title: ID
          type: string
          description: Unique identifier of this hotel.
        destinationId:
          title: ID
          type: string
          description: "Destination identifier this hotel belongs to. Source note: index."
          examples:
            - "804028047"
        name:
          $ref: "#/components/schemas/I18N"
          description: Hotel name, localised.
          examples:
            - en: Jumeirah Beach Hotel
        rating:
          type: number
          description: Hotel rating, in the range [0.0, 5.0].
          examples:
            - 4.5
        address:
          $ref: "#/components/schemas/I18N"
          examples:
            - en: Millenium Al Barsha
        latlngCoordinator:
          $ref: "#/components/schemas/LatlngCoordinator"
        logoURL:
          type: string
          examples:
            - https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
    PageResp:
      title: PageResp
      type: object
      description: Pagination data returned with the response.
      properties:
        total:
          type: integer
          format: int64
          description: >-
            Total number of items. A value of 0 means there are no items, or that totals are not
            supported for this query.
          examples:
            - 100
        hasMore:
          type: boolean
          description: Indicates whether further items remain to be fetched.
          examples:
            - true
    hotel.search.protocol.HotelListReq:
      title: HotelListReq
      type: object
      properties:
        hotelIds:
          title: IDs
          description: >-
            Explicit hotel IDs to search for; at most 50 entries. A longer array is
            rejected with code 100000400 — split it across several requests.
          type: array
          maxItems: 50
          items:
            type: string
          examples:
            - - "461850557"
              - "118062388"
        maxRatesPerHotel:
          default: 0
          description: >-
            **How many room rates to return for each hotel, ordered by price with the cheapest
            first. 0 (the default) returns every rate uncapped; use 1 to return only the cheapest
            rate per hotel, which suits listing pages.**
          type: integer
          format: int64
          examples:
            - 3
        checkIn:
          title: DateInt
          default: now()
          description: Check-in date; defaults to the current date.
          type: string
          examples:
            - "2026-01-01"
        checkOut:
          title: DateInt
          default: now()+7
          description: Check-out date; defaults to seven days from now.
          type: string
          examples:
            - "2026-01-03"
        countryCode:
          default: US
          description: Country code of the booker's point of sale, in ISO 3166-1 alpha-2 form (e.g. "US").
          type: string
          examples:
            - US
        residencyCode:
          default: US
          description: Booker's residency code, in ISO 3166-1 alpha-2 form (e.g. "US").
          type: string
          examples:
            - US
        nationalityCode:
          default: US
          description: Booker's nationality code, in ISO 3166-1 alpha-2 form (e.g. "US").
          type: string
          examples:
            - US
        roomOccupancies:
          type: array
          items:
            $ref: "#/components/schemas/hotel.supplier.domain.GuestPerRoom"
        destinationId:
          title: ID
          description: Region identifier. Required when destinationName is not supplied.
          type: string
          examples:
            - "804028047"
        destinationName:
          description: >-
            Region name. Required when destinationId is not supplied; the system automatically looks
            up cities matching this name.
          type: string
          examples:
            - Dubai
        pageNum:
          default: 1
          description: Page number. The first page is 1; values below 1 are rejected.
          type: integer
          format: int64
          minimum: 1
          examples:
            - 1
        pageSize:
          default: 50
          description: >-
            Page size. Defaults to 50 when omitted, and may not exceed 200 — a larger
            value is rejected with code 100000400 rather than being silently clamped.
          type: integer
          format: int64
          minimum: 1
          maximum: 200
          examples:
            - 50
        cursor:
          default: 0
          description: Cursor pointing at the next page.
          type: integer
          format: int64
          examples:
            - 0
        sortBy:
          description: >-
            Result ordering. Documented values: price-asc, price-desc, rating-desc, distance-asc.
            (The source types this as a free-form string — no enum constraint is declared.)
          type: string
          examples:
            - price-desc
      required:
        - checkIn
        - checkOut
        - roomOccupancies
    hotel.supplier.domain.GuestPerRoom:
      title: GuestPerRoom
      type: object
      properties:
        adultCount:
          description: AdultCount is the number of adults
          format: int64
          type: integer
          examples:
            - 2
        childrenAges:
          description: ChildrenAges contains ages of children
          type: array
          items:
            description: ChildrenAges contains ages of children
            format: int64
            type: integer
          examples:
            - - 2
      required:
        - adultCount
    hotel.search.protocol.HotelListResp:
      title: HotelListResp
      type: object
      properties:
        list:
          title: HotelList
          description: The hotels matched by the search.
          type: array
          items:
            $ref: "#/components/schemas/Hotel"
        basic:
          $ref: "#/components/schemas/HotelListBasicInfo"
          description: Contextual information about the search itself.
        total:
          description: >-
            Total number of items. A value of 0 means either that there are no items or that totals
            are not supported for this query.
          type: integer
          format: int64
          examples:
            - 100
        hasMore:
          description: Whether further items remain to be fetched.
          type: boolean
          examples:
            - true
      required:
        - basic
        - list
    HotelListBasicInfo:
      title: HotelListBasicInfo
      type: object
      properties:
        destination:
          $ref: "#/components/schemas/Destination"
          description: Details of the region the search covered.
          examples:
            - id: "804028047"
              name:
                en: Dubai
        sessionId:
          description: The session ID.
          type: string
          examples:
            - 374337a797454a344ad999c7730da01c
        statusRemark:
          type: string
          description: >-
            One human-readable sentence explaining a result that is empty or incomplete. Uses the
            same field name the contract already gives the advisory text beside `status` on
            CheckAvail and on every order. Absent when there is nothing to explain. Additive and
            optional.
          examples:
            - >-
              No supplier was searched for this request: no supplier is currently enabled for hotel
              search. This is a configuration state, not an absence of availability — retrying, or
              changing the dates or destination, will not change it. Contact your account manager.
        notices:
          type: array
          description: >-
            What this response does NOT contain, when the search succeeded but is not complete —
            a destination expansion that hit its cap, properties dropped because they could not be
            priced in the requested currency. Belongs to a result that HAS content; never emitted
            alongside `emptyReason`. Additive and optional.
          items:
            type: string
          examples:
            - - Showing the first 200 of 4318 properties matching "United Arab Emirates". Narrow to
                a city or area for full coverage.
        emptyReason:
          $ref: "#/components/schemas/HotelListEmptyReason"
          description: >-
            Machine-readable diagnosis of an empty `list`. Present ONLY when the emptiness is a
            platform or configuration state; absent when the suppliers were asked and simply had
            nothing. Additive and optional.
    HotelListEmptyReason:
      title: HotelListEmptyReason
      type: object
      description: >-
        Why a search came back with an empty `list` for a reason other than genuine zero
        availability. Additive to the mirrored contract.
      required:
        - code
      properties:
        code:
          type: string
          enum:
            - NO_SUPPLIER_ENABLED
            - NO_SUPPLIER_PERMITTED
            - ALL_SUPPLIERS_EXCLUDED
            - NO_SUPPLIER_ANSWERED
          description: >-
            `NO_SUPPLIER_ENABLED` — nothing is enabled for hotel search.
            `NO_SUPPLIER_PERMITTED` — suppliers exist, but none may serve your account on this
            search. `ALL_SUPPLIERS_EXCLUDED` — every candidate was excluded before the search ran.
            `NO_SUPPLIER_ANSWERED` — suppliers were called and all of them failed; this is the only
            one of the four worth retrying. Published to every caller — it names no supplier.
          examples:
            - NO_SUPPLIER_ENABLED
        suppliers:
          type: array
          description: >-
            Per-supplier detail — which supplier produced nothing, and why. Disclosed ONLY to
            accounts entitled to the supplier breakdown; most integrations will never receive this
            property, and its absence is not an error. `code` and `statusRemark` are complete
            without it.
          items:
            $ref: "#/components/schemas/HotelListEmptyReasonSupplier"
    HotelListEmptyReasonSupplier:
      title: HotelListEmptyReasonSupplier
      type: object
      required:
        - reason
        - supplierCode
      properties:
        supplierCode:
          type: string
          examples:
            - MOCK
        reason:
          type: string
          examples:
            - "TIMEOUT: supplier did not respond within 20000 ms"
    HotelRatesRespEnvelope:
      title: HotelRatesResp
      type: object
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.search.protocol.HotelRatesResp"
      x-display-name: hotel.search.protocol.HotelRatesResp
      x-primary-property: data
    hotel.search.protocol.HotelRatesReq:
      title: HotelRatesReq
      type: object
      properties:
        hotelId:
          title: ID
          type: string
          examples:
            - "461850557"
        checkIn:
          default: now()
          description: CheckIn is the check-in date, defaults to current date
          title: DateInt
          type: string
          examples:
            - "2026-01-01"
        checkOut:
          default: now()+7
          description: CheckOut is the check-out date, defaults to 7 days from now
          title: DateInt
          type: string
          examples:
            - "2026-01-03"
        countryCode:
          default: US
          description: >-
            CountryCode is the country code of the booker's point of sale in ISO 3166-1 alpha-2
            format (e.g., "US")
          type: string
          examples:
            - US
        residencyCode:
          default: US
          description: >-
            ResidencyCode is the residency code of the booker in ISO 3166-1 alpha-2 format (e.g.,
            "US")
          type: string
          examples:
            - US
        nationalityCode:
          default: US
          description: >-
            NationalityCode is the nationality code of the booker in ISO 3166-1 alpha-2 format
            (e.g., "US")
          type: string
          examples:
            - US
        roomOccupancies:
          type: array
          items:
            $ref: "#/components/schemas/hotel.supplier.domain.GuestPerRoom"
      required:
        - checkIn
        - checkOut
        - hotelId
        - roomOccupancies
    hotel.search.protocol.HotelRatesResp:
      title: HotelRatesResp
      type: object
      properties:
        rooms:
          description: rooms contains room packages
          type: array
          items:
            $ref: "#/components/schemas/Room"
            description: rooms contains room packages
    hotel.search.protocol.CheckAvailReq:
      title: CheckAvailReq
      type: object
      properties:
        ratePkgId:
          title: RatePkgId
          description: Unique identifier of this RatePkg.
          type: string
      required:
        - ratePkgId
    CheckAvailResp:
      title: CheckAvailResp
      type: object
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.search.protocol.CheckAvailResp"
      x-display-name: hotel.search.protocol.CheckAvailResp
      x-primary-property: data
    ARIChangedErr:
      title: ARIChangedErr
      type: object
      properties:
        code:
          type: integer
          examples:
            - 100001111
        msg:
          type: string
          examples:
            - ARI changed
    hotel.search.protocol.CheckAvailResp:
      title: CheckAvailResp
      type: object
      properties:
        status:
          title: CheckAvailStatus
          description: >-
            Availability outcome for the room. The source also states this field conveys other
            unavailability causes such as a credit-warning status, although only two enum values are
            defined.
          type: integer
          enum:
            - 1
            - 2
          x-enum-comments:
            - indicates the room is available for booking
            - indicates the room is not available
          x-enum-varnames:
            - CheckAvailStatusAvailable
            - CheckAvailStatusUnavailable
        roomRatePkg:
          title: RoomRatePkg
          description: Detailed rate package information, present when available.
          type: object
          properties:
            ratePkgId:
              title: RatePkgId
              description: Key input for the checkAvail and book APIs.
              type: string
            refundableMode:
              title: RefundableMode
              type: string
              enum:
                - full
                - partial
                - "no"
              x-enum-comments:
                - free cancellation
                - partial cancellation
                - not refundable
              x-enum-varnames:
                - RefundableModeFully
                - RefundableModePartially
                - RefundableModeNo
            refundableUntil:
              description: Instant up to which the stated refundableMode applies.
              type: string
              format: RFC3339 format
              examples:
                - 2006-01-02T15:04:05Z07:00
            cancelFees:
              $ref: "#/components/schemas/hotel.supplier.domain.CancelFees"
            originalRoomNaming:
              title: OriginalRoomNaming
              description: Room naming fields exactly as received from the supplier.
              type: object
              properties:
                id:
                  description: Unique identifier, i.e. the room code.
                  type: string
                name:
                  description: Room name as supplied by the supplier.
                  type: string
                supplier:
                  title: Supplier
                  description: Supplier id.
                  type: integer
            rate:
              title: Rate
              description: Price of a single room across all nights.
              type: object
              properties:
                commissionableRate:
                  title: Money
                  description: Basis for commission calculation.
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                netRate:
                  title: Money
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                grossRate:
                  title: Money
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                respectGrossRate:
                  description: When true, the client must honour GrossRate. Defaults to false.
                  type: boolean
              required:
                - netRate
            totalRate:
              title: Rate
              description: Total price covering all rooms and all nights.
              type: object
              properties:
                commissionableRate:
                  title: Money
                  description: Basis for commission calculation.
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                netRate:
                  title: Money
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                grossRate:
                  title: Money
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                respectGrossRate:
                  description: When true, the client must honour GrossRate. Defaults to false.
                  type: boolean
              required:
                - netRate
            rateComment:
              type: string
            includesPackaging:
              description: Marks the product as a package, for example a flight plus hotel combination.
              type: boolean
            checkIn:
              title: DateInt
              description: Check-in date. Defaults to the current date.
              type: string
              default: now()
              examples:
                - "2026-01-01"
              x-source-anomaly: >-
                Source `title` is "DateInt" while `type` is string and the example is the string
                "2026-01-01"; `default` is the literal expression "now()".
            checkOut:
              title: DateInt
              description: Check-out date. Defaults to seven days from the current date.
              type: string
              default: now()+7
              examples:
                - "2026-01-03"
              x-source-anomaly: >-
                Source `title` is "DateInt" while `type` is string and the example is the string
                "2026-01-03"; `default` is the literal expression "now()+7".
            board:
              title: Board
              description: "Board information: the standard meal plan, following the liteapi standard."
              type: object
              properties:
                boardId:
                  title: BoardId
                  description: Meal plan code, drawn from the standard enum.
                  type: string
                  enum:
                    - RO
                    - BB
                    - HB
                    - FB
                    - AI
                    - TI
                    - BI
                    - LU
                    - DI
                    - BD
                    - BL
                    - LD
                  x-enum-comments:
                    - |-
                      Basic meal plan types
                      Room Only - 仅住宿
                    - Bed and Breakfast - 含早餐
                    - Half Board - 半食宿（早+晚）
                    - Full Board - 全食宿（三餐）
                    - All Inclusive - 全包
                    - All Inclusive (alternate code) - 全包（备用代码）
                    - |-
                      Single meal types
                      Breakfast Included - 仅早餐
                    - Lunch Only - 仅午餐
                    - Dinner Only - 仅晚餐
                    - |-
                      Combination meal types
                      Breakfast and Dinner - 早+晚
                    - Breakfast and Lunch - 早+午
                    - Lunch and Dinner - 午+晚
                  x-enum-varnames:
                    - BoardIdRoomOnly
                    - BoardIdBedBreakfast
                    - BoardIdHalfBoard
                    - BoardIdFullBoard
                    - BoardIdAllInclusive
                    - BoardIdAllInclusiveTI
                    - BoardIdBreakfastOnly
                    - BoardIdLunchOnly
                    - BoardIdDinnerOnly
                    - BoardIdBreakfastDinner
                    - BoardIdBreakfastLunch
                    - BoardIdLunchDinner
                boardName:
                  title: I18N
                  description: Meal plan name, multilingual.
                  type: object
                  properties:
                    en:
                      description: English, the default system language.
                      type: string
                    zh:
                      description: Chinese, 中文.
                      type: string
                    ar:
                      description: Arabian, اللغة العربية.
                      type: string
                boardDesc:
                  title: I18N
                  description: Meal plan description, multilingual.
                  type: object
                  properties:
                    en:
                      description: English, the default system language.
                      type: string
                    zh:
                      description: Chinese, 中文.
                      type: string
                    ar:
                      description: Arabian, اللغة العربية.
                      type: string
              required:
                - boardId
            tax:
              title: Tax
              description: >-
                Taxes and fees. These are typically collected by the hotel on behalf of the
                government, are fixed costs, and are excluded from any markup applied during
                distribution, which is why they are itemised separately.
              type: object
              properties:
                total:
                  title: Money
                  type: object
                  properties:
                    currency:
                      description: For example "USD".
                      type: string
                    amount:
                      description: For example "14.50".
                      type: number
                  required:
                    - amount
                    - currency
                items:
                  type: array
                  items:
                    title: TaxItem
                    type: object
                    properties:
                      taxType:
                        description: For example VAT, SERVICE_CHARGE, CITY_TAX.
                        type: string
                      taxName:
                        type: string
                      amount:
                        title: Money
                        type: object
                        properties:
                          currency:
                            description: For example "USD".
                            type: string
                          amount:
                            description: For example "14.50".
                            type: number
                        required:
                          - amount
                          - currency
                      desc:
                        type: string
          required:
            - checkIn
            - checkOut
            - rate
            - ratePkgId
            - refundableMode
            - totalRate
        exchangeRateSnapshot:
          title: ExchangeRateSnapshot
          description: >-
            Exchange-rate snapshot captured at CheckAvail time and reused for Booking and for
            Cancellations/refunds (issue #73). Original source text — 汇率快照，在 CheckAvail 时捕获，用于
            Booking 和 Cancellations/refunds 时复用（issue #73）
          type: object
          properties:
            date:
              description: Exchange-rate date. Original source text — 汇率日期
              type: string
            usd:
              description: >-
                Contains only the currencies actually needed, for example {"aed": 0.27, "usd": 1.0,
                "eur": 1.1}. Original source text — 只包含需要的币种，如 {"aed": 0.27, "usd": 1.0, "eur": 1.1}
              type: object
              additionalProperties:
                type: number
              properties: {}
              x-go-map-key:
                type: string
              x-source-anomaly: >-
                The source declares `type: object` together with `items: {type: number}` and an
                empty `properties: {}`, plus `x-go-map-key: {type: string}`. This is a Go
                map[string]float serialised imprecisely. Rendered here as `additionalProperties:
                {type: number}`, which preserves the documented wire shape; the original `items`
                keyword is invalid on an object and has been dropped in favour of the equivalent map
                form.
    hotel.trade.protocol.BookReq:
      title: BookReq
      type: object
      required:
        - customerReferenceNo
        - guests
        - holder
        - ratePkgId
      properties:
        customerReferenceNo:
          description: >-
            Your own reference for this booking, and the idempotency key for the endpoint — retrying
            with the same value returns the original order instead of creating a second one. A UUID
            is the usual choice.
          type: string
          examples:
            - 9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50
        ratePkgId:
          description: >-
            RatePkgId identifying the rate being booked. Obtained from a HotelList or HotelRates
            response, and only resolvable within the session that produced it — send that session's
            id in the Session-Id header.
          title: RatePkgId
          type: string
        holder:
          $ref: "#/components/schemas/Holder"
          description: Holder contains the booking contact information
        guests:
          description: Guests contains the list of guests for this room
          type: array
          items:
            $ref: "#/components/schemas/Guest"
            description: Guests contains the list of guests for this room
        callbackUrl:
          description: >-
            Optional. Registers an outbound order-status webhook for this order: every later status
            change is POSTed to this address as an OrderStatusCallback, signed with your credential's
            webhook secret. Omit it and no callbacks are sent for the order.


            Must be **https**. That is a deliberate constraint rather than a transport preference —
            the delivery carries the signed order payload — and plain http, a private or loopback
            address, or a non-URL is refused as `100000400` / ERR.PARAM naming `callbackUrl`. The
            field was accepted and dropped before a dispatcher existed, so no configuration that was
            ever actually delivered to is refused by this.
          type: string
          format: uri
          examples:
            - https://partner.example.com/ttd/order-status
    Holder:
      title: Holder
      type: object
      required:
        - firstName
        - lastName
      properties:
        firstName:
          type: string
          examples:
            - John
        lastName:
          type: string
          examples:
            - Doe
        email:
          type: string
          examples:
            - john.doe@example.com
        phone:
          $ref: "#/components/schemas/Phone"
    Phone:
      title: Phone
      type: object
      properties:
        countryCode:
          description: AE
          type: string
        countryNumber:
          description: "971"
          type: integer
          format: int64
        number:
          description: "525757249"
          type: string
    Guest:
      title: Guest
      type: object
      description: >-
        One traveller on the booking.


        `gender`, `dateOfBirth` and `passportNumber` are OPTIONAL and additive: a body that omits
        them parses exactly as it always did. They exist because a connection point can declare
        `requiredGuestFields`, and the platform enforces that rule on every channel — until these
        three keys were accepted, a point configured to require a gender or a passport number turned
        every booking routed through it into a permanent refusal naming a field a partner had no way
        to send.


        THIS IS A TIGHTENING IN ONE DIRECTION, and it is intended. All three used to be discarded in
        silence, so a partner that sent `gender: "male"` had it dropped without a word. A value that
        cannot be understood is now refused as `100000400` / ERR.PARAM naming the field. Sending
        nothing is unchanged; sending something unparseable now fails loudly instead of quietly.
      required:
        - firstName
        - lastName
        - roomIndex
      properties:
        roomIndex:
          description: Assigned room index for this guest, starts from 1
          type: integer
          format: int64
        firstName:
          description: First name of this guest
          type: string
          examples:
            - John2
        lastName:
          description: Last name of this guest
          type: string
          examples:
            - Doe
        nationalityCode:
          description: Nationality code of this guest
          type: string
          examples:
            - US
        age:
          description: Age of this guest, only matters for children
          type: integer
          format: int64
          examples:
            - 18
        isChild:
          description: Indicates if this guest is a child, determined by clients themselves
          type: boolean
          examples:
            - false
        gender:
          description: >-
            Optional. Sent to the supplier when their contract asks for it (`requiredGuestFields`
            includes `gender`).


            Matched case-insensitively, and `M` / `F` are accepted as shorthand, because a partner's
            PMS emits whatever it emits. Anything outside the listed values is REFUSED rather than
            mapped to `UNSPECIFIED` — guessing a traveller's gender to satisfy a supplier's contract
            is worse than telling you the value was not understood.
          type: string
          enum:
            - MALE
            - FEMALE
            - OTHER
            - UNSPECIFIED
          examples:
            - MALE
        dateOfBirth:
          description: >-
            Optional. ISO `YYYY-MM-DD`. Required only when the supplier's contract asks for it
            (`requiredGuestFields` includes `dateOfBirth`), and for a child or infant, where an age
            alone does not identify the birthday the hotel checks at the desk. `age` remains accepted
            in its place.
          type: string
          format: date
          examples:
            - "2018-04-23"
        passportNumber:
          description: >-
            Optional, max 50 characters. Required only when the supplier's contract asks for it
            (`requiredGuestFields` includes `passportNumber`). Encrypted at rest and never returned
            in full — order reads show the last four characters only.
          type: string
          maxLength: 50
          examples:
            - X1234567
    BookRespEnvelope:
      title: BookResp
      type: object
      x-display-name: hotel.trade.protocol.BookResp
      x-primary-property: data
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.trade.protocol.BookResp"
    TimeoutErr:
      title: TimeoutErr
      type: object
      properties:
        code:
          type: integer
          examples:
            - 100000504
        msg:
          type: string
          examples:
            - timeout
    hotel.trade.protocol.BookResp:
      title: BookResp
      type: object
      properties:
        hotelOrder:
          $ref: "#/components/schemas/hotel.supplier.domain.HotelOrder"
    hotel.supplier.domain.HotelOrder:
      title: HotelOrder
      type: object
      required:
        - bookingTime
        - checkIn
        - checkOut
        - holder
        - netRate
        - platformReferenceNo
        - status
        - supplierReferenceNo
      properties:
        status:
          $ref: "#/components/schemas/OrderStatus"
          description: OrderStatus indicates the current status of the order
          examples:
            - 1
        statusRemark:
          type: string
          examples:
            - aborted
        checkIn:
          title: DateInt
          type: string
          default: now()
          description: CheckIn is the check-in date, defaults to current date
          examples:
            - "2026-01-01"
        checkOut:
          title: DateInt
          type: string
          default: now()+7
          description: CheckOut is the check-out date, defaults to 7 days from now
          examples:
            - "2026-01-03"
        nightCount:
          description: Number of nights for the stay
          type: integer
          format: int64
        roomCount:
          description: CheckOut is the check-out date for the booking
          type: integer
          format: int64
        bookingTime:
          description: BookingTime is when the booking was created
          type: string
          format: RFC3339 format
          examples:
            - "2026-01-01T10:00:00Z"
        hotelConfirmNo:
          description: HotelConfirmNo is the confirmation number from the hotel
          type: string
          examples:
            - "123456"
        holder:
          $ref: "#/components/schemas/Holder"
          description: Holder contains the person who made the booking
          examples:
            - email: johndoe@example.com
              firstName: John
              lastName: Doe
              phone:
                countryCode: "1"
                number: "1234567890"
        platformReferenceNo:
          description: PlatformReferenceNo is the internal platform order identifier
          title: ID
          type: string
          examples:
            - "1234567890"
        customerReferenceNo:
          description: CustomerReferenceNo is the unique order identifier from the customer
          type: string
          examples:
            - "1234567890"
        commissionableRate:
          $ref: "#/components/schemas/Money"
          description: used for commission calculation
        netRate:
          $ref: "#/components/schemas/Money"
        grossRate:
          $ref: "#/components/schemas/Money"
        respectGrossRate:
          description: You should respect GrossRate if RespectGrossRate is true; default as false
          type: boolean
        cancelTime:
          description: CancelTime is when the booking was cancelled, if applicable
          type: string
          format: RFC3339 format
          examples:
            - "2026-01-02T10:00:00Z"
        cancelReason:
          description: CancelReason contains the reason if the order was cancelled
          type: string
          examples:
            - Customer requested cancellation
        refundedPrice:
          $ref: "#/components/schemas/Money"
          description: RefundedPrice is the amount that has been refunded to the customer
          examples:
            - amount: 99
              currency: USD
        supplier:
          title: Supplier
          type: integer
          examples:
            - 20000001
        supplierReferenceNo:
          description: "SupplierReferenceNo is the unique order identifier from the supplier\t// Supplier identifies which supplier processed this order"
          type: string
        hotel:
          $ref: "#/components/schemas/OrderHotelInfo"
          description: hotel-specific information
        rooms:
          description: detailed information for each booked room
          type: array
          items:
            $ref: "#/components/schemas/OrderRoomInfo"
            description: detailed information for each booked room
    OrderStatus:
      title: OrderStatus
      type: integer
      description: |
        Status indicates the current status of the order after cancellation.

        Integer-encoded enumeration:
          0 = OrderStatus_Unknown      — Unknown
          1 = OrderStatus_Confirming   — Confirming
          2 = OrderStatus_Confirmed    — Confirmed
          3 = OrderStatus_Cancelled    — Cancelled
          4 = OrderStatus_Failed       — Failed
          5 = OrderStatus_CancelFailed — CancelFailed
      enum:
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
      x-enum-comments:
        - Unknown
        - Confirming
        - Confirmed
        - Cancelled
        - Failed
        - CancelFailed
      x-enum-varnames:
        - OrderStatus_Unknown
        - OrderStatus_Confirming
        - OrderStatus_Confirmed
        - OrderStatus_Cancelled
        - OrderStatus_Failed
        - OrderStatus_CancelFailed
    OrderHotelInfo:
      title: OrderHotelInfo
      type: object
      description: Hotel detail attached to an order. No properties are declared required.
      properties:
        hotelId:
          title: ID
          type: string
        destinationId:
          title: ID
          description: index
          type: string
          examples:
            - "804028047"
        name:
          $ref: "#/components/schemas/I18N"
          description: hotel name
          examples:
            - en: Jumeirah Beach Hotel
        rating:
          description: Rating, hotel rating, range [0.0, 5.0]
          type: number
          examples:
            - 4.5
        address:
          $ref: "#/components/schemas/I18N"
          examples:
            - en: Millenium Al Barsha
        latlngCoordinator:
          $ref: "#/components/schemas/LatlngCoordinator"
        logoURL:
          type: string
          examples:
            - https://static.hotelbyte.com/Images/Hotel/804028047_1.jpg
    OrderRoomInfo:
      title: OrderRoomInfo
      type: object
      required:
        - checkIn
        - checkOut
        - hotelId
        - rate
        - ratePkgId
        - roomTypeId
        - roomTypeName
        - totalRate
      properties:
        roomTypeId:
          description: standardized roomTypeId, e.g. "R001"
          type: string
        roomTypeName:
          $ref: "#/components/schemas/I18N"
          description: >-
            standardized room type name; if not recognized, we'll give a default name like "Standard
            Room"
        hotelId:
          description: hotelId, duplicate of parent HotelId for indicating identified room
          title: ID
          type: string
        rates:
          title: RoomRatePkgList
          description: core structure, room offers under this room
          type: array
          items:
            $ref: "#/components/schemas/hotel.supplier.domain.RoomRatePkg"
            title: RoomRatePkg
            description: core structure, room offers under this room
        ratePkgId:
          description: used as key input for checkAvail & book APIs
          title: RatePkgId
          type: string
        refundableMode:
          $ref: "#/components/schemas/RefundableMode"
        refundableUntil:
          description: RefundableMode is valid until RefundableUntil
          type: string
          format: RFC3339 format
          examples:
            - 2006-01-02T15:04:05Z07:00
        cancelFees:
          $ref: "#/components/schemas/hotel.supplier.domain.CancelFees"
        originalRoomNaming:
          $ref: "#/components/schemas/OriginalRoomNaming"
          description: origin room naming fields from supplier
        rate:
          $ref: "#/components/schemas/Rate"
          description: single room price for multiple nights
        totalRate:
          $ref: "#/components/schemas/Rate"
          description: total price for multiple rooms (and multiple nights)
        rateComment:
          type: string
        includesPackaging:
          description: Whether this is a packaged product (e.g., flight+hotel combo)
          type: boolean
        checkIn:
          title: DateInt
          type: string
          default: now()
          description: CheckIn is the check-in date, defaults to current date
          examples:
            - "2026-01-01"
        checkOut:
          title: DateInt
          type: string
          default: now()+7
          description: CheckOut is the check-out date, defaults to 7 days from now
          examples:
            - "2026-01-03"
        board:
          $ref: "#/components/schemas/Board"
          description: Board info - Standard meal plan following liteapi standard
        tax:
          $ref: "#/components/schemas/Tax"
          description: >-
            Taxes and fees, generally collected by hotels on behalf of the government, are fixed
            costs and do not participate in the price increase during the distribution process.
            Therefore, they are listed separately.
        roomIndex:
          description: room index
          type: integer
          format: int64
        guests:
          description: information about all guests in this room
          type: array
          items:
            $ref: "#/components/schemas/Guest"
            description: information about all guests in this room
        refundInfo:
          type: array
          items:
            $ref: "#/components/schemas/hotel.supplier.domain.OrderRoomRefundInfo"
    RefundableMode:
      title: RefundableMode
      type: string
      enum:
        - full
        - partial
        - "no"
      description: |-
        Refundability of the rate package:
          full    = RefundableModeFully     - free cancellation
          partial = RefundableModePartially - partial cancellation
          no      = RefundableModeNo        - not refundable
      x-enum-comments:
        - free cancellation
        - partial cancellation
        - not refundable
      x-enum-varnames:
        - RefundableModeFully
        - RefundableModePartially
        - RefundableModeNo
    BoardId:
      title: BoardId
      type: string
      description: |-
        BoardId is the meal plan code (standard enum).
        Basic meal plan types:
          RO = Room Only - 仅住宿                                    (BoardIdRoomOnly)
          BB = Bed and Breakfast - 含早餐                            (BoardIdBedBreakfast)
          HB = Half Board - 半食宿（早+晚）                           (BoardIdHalfBoard)
          FB = Full Board - 全食宿（三餐）                            (BoardIdFullBoard)
          AI = All Inclusive - 全包                                  (BoardIdAllInclusive)
          TI = All Inclusive (alternate code) - 全包（备用代码）        (BoardIdAllInclusiveTI)
        Single meal types:
          BI = Breakfast Included - 仅早餐                           (BoardIdBreakfastOnly)
          LU = Lunch Only - 仅午餐                                   (BoardIdLunchOnly)
          DI = Dinner Only - 仅晚餐                                  (BoardIdDinnerOnly)
        Combination meal types:
          BD = Breakfast and Dinner - 早+晚                          (BoardIdBreakfastDinner)
          BL = Breakfast and Lunch - 早+午                           (BoardIdBreakfastLunch)
          LD = Lunch and Dinner - 午+晚                              (BoardIdLunchDinner)
      enum:
        - RO
        - BB
        - HB
        - FB
        - AI
        - TI
        - BI
        - LU
        - DI
        - BD
        - BL
        - LD
      x-enum-varnames:
        - BoardIdRoomOnly
        - BoardIdBedBreakfast
        - BoardIdHalfBoard
        - BoardIdFullBoard
        - BoardIdAllInclusive
        - BoardIdAllInclusiveTI
        - BoardIdBreakfastOnly
        - BoardIdLunchOnly
        - BoardIdDinnerOnly
        - BoardIdBreakfastDinner
        - BoardIdBreakfastLunch
        - BoardIdLunchDinner
      x-enum-descriptions:
        - |-
          Basic meal plan types
          Room Only - 仅住宿
        - Bed and Breakfast - 含早餐
        - Half Board - 半食宿（早+晚）
        - Full Board - 全食宿（三餐）
        - All Inclusive - 全包
        - All Inclusive (alternate code) - 全包（备用代码）
        - |-
          Single meal types
          Breakfast Included - 仅早餐
        - Lunch Only - 仅午餐
        - Dinner Only - 仅晚餐
        - |-
          Combination meal types
          Breakfast and Dinner - 早+晚
        - Breakfast and Lunch - 早+午
        - Lunch and Dinner - 午+晚
    hotel.supplier.domain.OrderRoomRefundInfo:
      title: OrderRoomRefundInfo
      type: object
      required:
        - date
        - refunded
        - refundedMoney
      properties:
        date:
          description: Date for which the refund applies
          title: DateInt
          type: string
        refunded:
          description: Whether the refund has been processed
          type: boolean
        refundedMoney:
          $ref: "#/components/schemas/Money"
          description: Amount of money refunded for this date
    hotel.trade.protocol.QueryOrdersReq:
      title: QueryOrdersReq
      type: object
      description: >-
        Filter criteria for an order query. The source declares no required properties, so every
        filter is optional.
      properties:
        customerReferenceNos:
          description: customer reference numbers to search for
          type: array
          items:
            description: customer reference numbers to search for
            type: string
        supplierReferenceNos:
          description: supplier reference numbers to search for
          type: array
          items:
            description: supplier reference numbers to search for
            type: string
        checkInTimeWindow:
          $ref: "#/components/schemas/TimeWindow"
          description: filters orders by check-in date range
        checkOutTimeWindow:
          $ref: "#/components/schemas/TimeWindow"
          description: filters orders by check-out date range
        bookingTimeWindow:
          $ref: "#/components/schemas/TimeWindow"
          description: filters orders by creation date range
        freeCancelTimeWindow:
          $ref: "#/components/schemas/TimeWindow"
          description: filters orders by free cancel date range
        cancelledTimeWindow:
          $ref: "#/components/schemas/TimeWindow"
          description: filters orders by cancellation date range
        statusList:
          description: filters orders by status
          type: array
          items:
            $ref: "#/components/schemas/OrderStatus"
            description: filters orders by status
    TimeWindow:
      title: TimeWindow
      type: object
      description: Inclusive/exclusive semantics are not documented. No properties are declared required.
      properties:
        start:
          type: string
          format: RFC3339 format
          examples:
            - 2006-01-02T15:04:05Z07:00
        end:
          type: string
          format: RFC3339 format
          examples:
            - 2006-01-02T15:04:05Z07:00
    QueryOrdersRespEnvelope:
      title: QueryOrdersResp
      type: object
      description: >-
        Standard response envelope. The source titles this object "QueryOrdersResp" and also gives
        display name "hotel.trade.protocol.QueryOrdersResp", which collides with the inner payload
        schema of the same title; it is renamed here purely to disambiguate. The source marks "data"
        as the primary property. No properties are declared required.
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.trade.protocol.QueryOrdersResp"
    RateLimitErr:
      title: RateLimitErr
      type: object
      description: Error payload returned when the caller exceeds the rate limit.
      properties:
        code:
          type: integer
          examples:
            - 100000429
        msg:
          type: string
          examples:
            - quota limit exceed
    hotel.trade.protocol.QueryOrdersResp:
      title: QueryOrdersResp
      type: object
      properties:
        orders:
          description: Orders contains the list of matching orders
          type: array
          items:
            $ref: "#/components/schemas/Order"
    Order:
      title: Order
      type: object
      description: A single booking order. The source declares no required properties on this object.
      properties:
        status:
          $ref: "#/components/schemas/OrderStatus"
          description: OrderStatus indicates the current status of the order
          examples:
            - 1
        statusRemark:
          type: string
          examples:
            - aborted
        checkIn:
          title: DateInt
          description: CheckIn is the check-in date, defaults to current date
          type: string
          default: now()
          examples:
            - "2026-01-01"
        checkOut:
          title: DateInt
          description: CheckOut is the check-out date, defaults to 7 days from now
          type: string
          default: now()+7
          examples:
            - "2026-01-03"
        nightCount:
          description: Number of nights for the stay
          type: integer
          format: int64
        roomCount:
          description: >-
            Number of rooms in the booking. NOTE: the source description for this field literally
            reads "CheckOut is the check-out date for the booking", which is a copy/paste error
            upstream - the field is an int64 count, not a date.
          type: integer
          format: int64
        bookingTime:
          description: BookingTime is when the booking was created
          type: string
          format: RFC3339 format
          examples:
            - "2026-01-01T10:00:00Z"
        hotelConfirmNo:
          description: HotelConfirmNo is the confirmation number from the hotel
          type: string
          examples:
            - "123456"
        holder:
          $ref: "#/components/schemas/Holder"
          description: Holder contains the person who made the booking
          examples:
            - email: johndoe@example.com
              firstName: John
              lastName: Doe
              phone:
                countryCode: "1"
                number: "1234567890"
        platformReferenceNo:
          title: ID
          description: PlatformReferenceNo is the internal platform order identifier
          type: string
          examples:
            - "1234567890"
        customerReferenceNo:
          description: CustomerReferenceNo is the unique order identifier from the customer
          type: string
          examples:
            - "1234567890"
        commissionableRate:
          $ref: "#/components/schemas/Money"
          description: used for commission calculation
        netRate:
          $ref: "#/components/schemas/Money"
        grossRate:
          $ref: "#/components/schemas/Money"
        respectGrossRate:
          description: You should respect GrossRate if RespectGrossRate is true; default as false
          type: boolean
        cancelTime:
          description: CancelTime is when the booking was cancelled, if applicable
          type: string
          format: RFC3339 format
          examples:
            - "2026-01-02T10:00:00Z"
        cancelReason:
          description: CancelReason contains the reason if the order was cancelled
          type: string
          examples:
            - Customer requested cancellation
        refundedPrice:
          $ref: "#/components/schemas/Money"
          description: RefundedPrice is the amount that has been refunded to the customer
          examples:
            - amount: 99
              currency: USD
        supplier:
          title: Supplier
          type: integer
          examples:
            - 20000001
        supplierReferenceNo:
          description: >-
            SupplierReferenceNo is the unique order identifier from the supplier. NOTE: the raw
            source description is "SupplierReferenceNo is the unique order identifier from the
            supplier\t// Supplier identifies which supplier processed this order" - a leaked Go
            struct-tag comment belonging to the adjacent "supplier" field.
          type: string
        hotel:
          $ref: "#/components/schemas/OrderHotelInfo"
          description: hotel-specific information
        rooms:
          description: detailed information for each booked room
          type: array
          items:
            $ref: "#/components/schemas/OrderRoomInfo"
    hotel.trade.protocol.OrderVoucherReq:
      title: OrderVoucherReq
      type: object
      description: >-
        At least one of the three references is required. Supplying
        `platformReferenceNo` always identifies an order uniquely; the other two may not,
        in which case the call is refused rather than answered with a guess.
      properties:
        customerReferenceNo:
          type: string
          description: Your own reference, as sent on Book.
        platformReferenceNo:
          type: string
          description: Our order number, as returned by Book and QueryOrders.
        supplierReferenceNo:
          type: string
          description: The supplier's reference, as returned by Book.
        includeDocument:
          type: boolean
          default: false
          description: >-
            Return the PDF inline as base64 in `voucher.content` as well as the link.
            Refused with 100001005 for documents above 8 MB.
    DocumentSignature:
      title: DocumentSignature
      type: object
      description: >-
        The platform's integrity claim over the exact bytes of the issued document.
        `digest` is what you check: SHA-256 the file you received, lowercase hex, and
        compare. `signature` is a detached HMAC that only the platform can verify — it is
        returned so the claim is auditable, not so you can verify it yourself.
      properties:
        alg:
          type: string
          const: HMAC-SHA256
        keyId:
          type: string
          description: Which platform key signed it.
          example: ttd-derived-v1
        digest:
          type: string
          description: Lowercase hex SHA-256 of the document bytes, as issued.
          example: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
        signature:
          type: string
          description: The detached signature over the manifest.
        signedAt:
          type: string
          format: date-time
      required:
        - alg
        - keyId
        - digest
        - signature
        - signedAt
    OrderVoucherDocument:
      title: OrderVoucherDocument
      type: object
      properties:
        voucherNumber:
          type: string
          example: VCH-TTD-2026-000042-01
        version:
          type: integer
          description: 1-based. A regenerated voucher supersedes the previous version.
        issuedAt:
          type: string
          format: date-time
        contentType:
          type: string
          example: application/pdf
        byteSize:
          type: integer
        verifyUrl:
          type: string
          format: uri
          description: The public verification page this voucher's QR code opens.
        downloadUrl:
          type: string
          format: uri
          description: Time-limited object URL for the PDF.
        expiresIn:
          type: integer
          description: Seconds `downloadUrl` remains valid.
        signature:
          $ref: "#/components/schemas/DocumentSignature"
          description: >-
            Absent for a voucher rendered before document signing was introduced. Omitted
            rather than fabricated.
        content:
          type: object
          description: Present only when `includeDocument` was requested.
          properties:
            contentType:
              type: string
            byteSize:
              type: integer
            base64:
              type: string
              format: byte
          required:
            - contentType
            - byteSize
            - base64
      required:
        - voucherNumber
        - version
        - issuedAt
        - contentType
        - byteSize
        - verifyUrl
        - downloadUrl
        - expiresIn
    OrderVoucherRespEnvelope:
      title: OrderVoucherResp
      type: object
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.trade.protocol.OrderVoucherResp"
      x-display-name: hotel.trade.protocol.OrderVoucherResp
      x-primary-property: data
    hotel.trade.protocol.OrderVoucherResp:
      title: OrderVoucherResp
      type: object
      properties:
        customerReferenceNo:
          type: string
        platformReferenceNo:
          type: string
        supplierReferenceNo:
          type: string
        status:
          type: string
          enum:
            - GENERATED
            - NOT_GENERATED
            - PENDING
            - FAILED
            - CANCELLED
          description: >-
            `GENERATED` is the only status that carries a document. `CANCELLED` withholds
            it deliberately: a reissued voucher for a cancelled stay is stamped "not valid
            for check-in".
        voucher:
          $ref: "#/components/schemas/OrderVoucherDocument"
          description: Present only when `status` is `GENERATED`.
      required:
        - platformReferenceNo
        - status
    hotel.trade.protocol.CancelReq:
      title: CancelReq
      type: object
      properties:
        customerReferenceNo:
          type: string
        supplierReferenceNo:
          type: string
        reason:
          type: string
      required:
        - customerReferenceNo
        - supplierReferenceNo
    CancelRespEnvelope:
      title: CancelResp
      type: object
      properties:
        code:
          type: integer
        msg:
          type: string
        data:
          $ref: "#/components/schemas/hotel.trade.protocol.CancelResp"
      x-display-name: hotel.trade.protocol.CancelResp
      x-primary-property: data
    hotel.trade.protocol.CancelResp:
      title: CancelResp
      type: object
      properties:
        serviceFee:
          $ref: "#/components/schemas/Money"
          description: ServiceFee is the service fee charged by supplier, not refunded
        status:
          $ref: "#/components/schemas/OrderStatus"
          description: Status indicates the current status of the order after cancellation
    NotFoundErr:
      title: NotFoundErr
      type: object
      properties:
        code:
          type: integer
          examples:
            - 100000404
        msg:
          type: string
          examples:
            - not found
    ErrorResponse:
      title: ErrorResponse
      type: object
      description: >-
        Returned when a call does not succeed. Always check `code` — some business failures are
        delivered with HTTP 200.
      properties:
        code:
          type: integer
          description: Business error code. Non-zero on failure.
          examples:
            - 100000400
        msg:
          type: string
          description: Human-readable explanation of the failure.
          examples:
            - param error
      required:
        - code
        - msg
    OrderStatusCallback:
      title: OrderStatusCallback
      type: object
      description: Body POSTed to a partner's `callbackUrl` when an order's status changes.
      properties:
        customerReferenceNo:
          type: string
          description: The partner's own order reference, as supplied on Book.
          examples:
            - REF123456
        hotelConfirmNo:
          type: string
          description: Hotel confirmation number. May be empty for some events.
          examples:
            - HCN789012
        event:
          type: string
          enum:
            - order_created
            - order_paid
            - order_cancelled
          description: The status change being reported.
        eventTime:
          type: integer
          format: int64
          description: When the event occurred, in Unix milliseconds.
          examples:
            - 1704067200000
      required:
        - customerReferenceNo
        - event
        - eventTime
