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

# hotel-search

> Search live hotel inventory and rates

Search live hotel inventory and nightly rates for a destination and stay window. It handles requests like "three nights in Lisbon next weekend for two adults" or "family room in Rome with one child in August". Each result includes an `htl_*` offer token you can hand to the trip tool to start a booking.


## OpenAPI

````yaml api-reference/public-api.yaml POST /v1/hotel_search
openapi: 3.0.0
info:
  title: Jinko Public API
  version: 0.1.0
  description: >-
    Curated public REST surface for Jinko. Authenticated with jnk_ API keys. See
    https://docs.gojinko.com for guides.


    ### Per-end-user attribution


    On booking calls you may send an optional `X-End-User-Id` request header to
    attribute the booking to one of your own end users (for per-end-user
    attribution and rate-limiting). The value is an **opaque, tenant-scoped**
    identifier that you choose — not a Jinko account id. Omit it to book as the
    tenant. WorkOS-shaped values (prefixed `user_` or `org_`) are rejected.
servers: []
security: []
paths:
  /v1/hotel_search:
    post:
      tags:
        - Hotels
      summary: Search live hotel inventory and rates
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HotelSearchRequest'
      responses:
        '200':
          description: Matching hotels
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HotelSearchResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: BAD_REQUEST
                  message: Malformed JSON in request body.
                  doc_url: https://docs.gojinko.com/concepts/errors
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: AUTH_REQUIRED
                  message: Invalid or expired API key.
                  doc_url: https://docs.gojinko.com/api-reference/authentication
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: BAD_REQUEST
                  message: >-
                    origins: origins is required; trip_type: trip_type is
                    required
                  doc_url: https://docs.gojinko.com/concepts/errors
        '429':
          description: Rate limit or quota exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: RATE_LIMITED
                  message: Rate limit or quota exceeded.
                  doc_url: https://docs.gojinko.com/concepts/errors
        '502':
          description: Upstream service error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: UPSTREAM_ERROR
                  message: Upstream travel provider returned an error. Please retry.
                  doc_url: https://docs.gojinko.com/concepts/errors
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
components:
  schemas:
    HotelSearchRequest:
      type: object
      properties:
        query:
          type: string
          example: Paris
        city_name:
          type: string
        country_code:
          type: string
          minLength: 2
          maxLength: 2
        latitude:
          type: number
        longitude:
          type: number
        radius_km:
          type: number
          minimum: 0
          exclusiveMinimum: true
          maximum: 50
        place_id:
          type: string
        hotel_ids:
          type: array
          items:
            type: string
        checkin:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        checkout:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        occupancies:
          type: array
          items:
            $ref: '#/components/schemas/Occupancy'
        adults:
          type: integer
          minimum: 1
        children:
          type: array
          items:
            type: integer
        rooms:
          type: integer
          minimum: 1
        currency:
          type: string
        guest_nationality:
          type: string
          minLength: 2
          maxLength: 2
        min_rating:
          type: number
        min_star_rating:
          type: integer
          minimum: 1
          maximum: 5
        star_rating:
          type: integer
          minimum: 1
          maximum: 5
        max_star_rating:
          type: integer
          minimum: 1
          maximum: 5
        min_reviews:
          type: integer
        max_results:
          type: integer
          description: Page size — max hotels returned (the limit). Default 50.
        offset:
          type: integer
          minimum: 0
          description: >-
            Pagination offset — skip this many hotels at the upstream search.
            Default 0.
        max_budget_per_night:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: >-
            Keep only hotels whose cheapest per-night price (per room, in the
            request currency) is within this budget; qualifying hotels keep all
            their rates. Destination searches automatically scan deeper into the
            hotel catalog when too few hotels fit the budget. Prefer a larger
            max_results over offset paging when this is set.
          example: 150
        hotel_type_ids:
          type: array
          items:
            type: string
        chain_ids:
          type: array
          items:
            type: string
        facility_ids:
          type: array
          items:
            type: string
        intent:
          $ref: '#/components/schemas/IntentInput'
      required:
        - checkin
        - checkout
      example:
        city_name: Paris
        country_code: fr
        checkin: '2026-09-01'
        checkout: '2026-09-04'
        adults: 2
        currency: USD
    HotelSearchResponse:
      type: object
      properties:
        hotels:
          type: array
          items:
            $ref: '#/components/schemas/Hotel'
        total:
          type: number
          example: 87
        warnings:
          type: array
          items:
            type: string
          description: >-
            Non-fatal advisories, e.g. budget-filter outcomes or ignored
            filters.
        budget_filter:
          $ref: '#/components/schemas/BudgetFilterMeta'
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            doc_url:
              type: string
          required:
            - code
            - message
      required:
        - error
    Occupancy:
      type: object
      properties:
        adults:
          type: integer
          minimum: 1
        children_ages:
          type: array
          items:
            type: integer
      required:
        - adults
    IntentInput:
      type: object
      properties:
        user_intent:
          type: string
          nullable: true
          description: >-
            The user's natural-language intent: the Alpic PII-stripped
            paraphrase when available, else a best-effort fallback to the
            client-provided NL query.
          example: find a cheap flight to Tokyo
    Hotel:
      type: object
      properties:
        hotel_id:
          type: string
          example: htl_8f21a9c0
        name:
          type: string
          example: Hôtel Le Marais
        address:
          type: string
          example: 12 Rue de Rivoli
        city:
          type: string
          example: Paris
        country_code:
          type: string
          example: FR
        star_rating:
          type: number
          example: 4
        rating:
          type: number
          example: 8.6
        review_count:
          type: number
          example: 1243
        images:
          type: array
          items:
            type: string
          example:
            - https://images.gojinko.com/hotels/htl_8f21a9c0/1.jpg
        thumbnail_url:
          type: string
          example: https://images.gojinko.com/hotels/htl_8f21a9c0/thumb.jpg
        rooms:
          type: array
          items:
            nullable: true
    BudgetFilterMeta:
      type: object
      properties:
        max_budget_per_night:
          type: number
          example: 150
        currency:
          type: string
          example: EUR
        nights:
          type: integer
          example: 3
        pages_fetched:
          type: integer
          example: 2
        catalog_exhausted:
          type: boolean
          description: >-
            True when the destination ran out of candidate hotels before the
            fill target.
        hotels_dropped:
          type: integer
          example: 34
      description: >-
        How the max_budget_per_night filter shaped the response (present only
        when set).
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    BearerAuth:
      type: http
      scheme: bearer

````