openapi: 3.0.0
info:
  title: Skyscanner Car Hire API
  description: |
    Search Skyscanner car hire for a pickup place, dates and times.

    Cars come in Skyscanner's order, the first 15 of the search, with their size class, transmission, seats, bags, photo and rental company. Each car carries the cheapest offers Skyscanner shows for it, usually 3, each with the booking site's total price for the rental, fuel policy, mileage, cancellation and cover terms, pickup desk and booking link. Offers from a booking site that answers Skyscanner late can be missing. Prices are in US dollars.

    A `pickup` name searches the first place Skyscanner suggests for it, and `search_information.pickup` names the place searched. Its `entity_id` can be passed back as `pickup_id` to search that exact place.
  version: 1.0.0
servers:
  - url: https://www.searchapi.io/api/v1
paths:
  /search:
    get:
      summary: Skyscanner Car Hire Search
      security:
        - ApiKeyAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: engine
          in: query
          required: true
          description: 'Search engine. Must be set to: `skyscanner_car_hire`'
          schema:
            type: string
            enum: ["skyscanner_car_hire"]
        - name: pickup
          in: query
          required: false
          description: Pickup place to search, such as `LAX` or `Orlando`. The search runs on the first place Skyscanner suggests for it, often the main airport. English names work best, for example `Tokyo` rather than `東京`. Postal codes such as `90210` find no place. Use the city or airport name instead. Up to 256 characters, fewer in non-Latin scripts. Cannot contain `/`, `%`, `\` or control characters such as line breaks, and must contain a letter or a digit. Required unless `pickup_id` is set.
          schema:
            type: string
            maxLength: 256
            pattern: '^(?=.*[^\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F])[^/%\\\x00-\x1F\x7F]*$'
        - name: pickup_id
          in: query
          required: false
          description: Skyscanner id of the pickup place, such as `95673368` for Los Angeles International. With an id, `search_information.pickup` carries the place's id and coordinates but not its name or type. Cannot be used with `pickup`.
          schema:
            type: string
            pattern: '^\d{1,10}$'
        - name: pickup_date
          in: query
          required: true
          description: Pickup date in YYYY-MM-DD format, from today.
          schema:
            type: string
            format: date
        - name: pickup_time
          in: query
          required: false
          description: Pickup time in HH:MM format, on a 24-hour clock. A search without it picks up at 10:00. A pickup time already passed at the pickup place can return fewer offers or none.
          schema:
            type: string
            pattern: '^(?:[01]\d|2[0-3]):[0-5]\d$'
        - name: dropoff_date
          in: query
          required: true
          description: Drop-off date in YYYY-MM-DD format, on or after `pickup_date`.
          schema:
            type: string
            format: date
        - name: dropoff_time
          in: query
          required: false
          description: Drop-off time in HH:MM format, on a 24-hour clock. A search without it drops off at 10:00. The drop-off must come after the pickup.
          schema:
            type: string
            pattern: '^(?:[01]\d|2[0-3]):[0-5]\d$'
        - name: driver_age
          in: query
          required: false
          description: Age of the driver, from 18 to 99. A search without it is for a driver of 30.
          schema:
            type: integer
            minimum: 18
            maximum: 99
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          description: Validation Error. There is an issue with query parameters, such as missing required parameters or invalid values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Authentication Error. The API key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate Limit Exceeded. The number of allowed requests has been exceeded. Consider upgrading your plan or waiting for the limit to reset.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server Error. Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Timeout. We could not retrieve results in 90 seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: 'Use Bearer authentication. Format: "Bearer YOUR_API_KEY"'
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: Pass API key as query parameter
  schemas:
    SearchResponse:
      type: object
      properties:
        search_metadata:
          $ref: '#/components/schemas/SearchMetadata'
        search_parameters:
          $ref: '#/components/schemas/SearchParameters'
        search_information:
          $ref: '#/components/schemas/SearchInformation'
        cars:
          type: array
          items:
            $ref: '#/components/schemas/Car'
          description: "Cars for the search, in Skyscanner's order"
        error:
          type: string
          description: "Error message describing what went wrong"
    SearchMetadata:
      type: object
      required: [status, created_at]
      properties:
        id:
          type: string
          description: "Unique identifier for the search request"
        status:
          type: string
          description: "Status of the search request"
        created_at:
          type: string
          format: date-time
          description: "Timestamp when the search was created"
        request_time_taken:
          type: number
          description: "Time taken to make the request in seconds"
        parsing_time_taken:
          type: number
          description: "Time taken to parse the results in seconds"
        total_time_taken:
          type: number
          description: "Total time taken for the search in seconds"
        request_url:
          type: string
          description: "Skyscanner results page for this search"
        html_url:
          type: string
          description: "URL to view the raw results"
        json_url:
          type: string
          description: "URL to view JSON results"
    SearchParameters:
      type: object
      properties:
        engine:
          type: string
          description: "Search engine used"
        pickup:
          type: string
          description: "Pickup place searched by name"
        pickup_id:
          type: string
          description: "Skyscanner id of the pickup place searched"
        pickup_date:
          type: string
          description: "Pickup date searched"
        pickup_time:
          type: string
          description: "Pickup time searched"
        dropoff_date:
          type: string
          description: "Drop-off date searched"
        dropoff_time:
          type: string
          description: "Drop-off time searched"
        driver_age:
          type: string
          description: "Age of the driver searched"
    SearchInformation:
      type: object
      required: [total_results, currency, pickup]
      properties:
        total_results:
          type: integer
          description: "Number of cars Skyscanner found for the search"
        currency:
          type: string
          description: "Currency of every price, such as USD"
        pickup:
          $ref: '#/components/schemas/Pickup'
    Pickup:
      type: object
      required: [entity_id]
      properties:
        entity_id:
          type: string
          description: "Skyscanner id of the place searched, usable as pickup_id"
        name:
          type: string
          description: "Name of the place searched"
        type:
          type: string
          description: "Kind of place searched, such as airport, city or train_station"
        gps_coordinates:
          $ref: '#/components/schemas/GpsCoordinates'
    GpsCoordinates:
      type: object
      required: [latitude, longitude]
      properties:
        latitude:
          type: number
          description: "Latitude"
        longitude:
          type: number
          description: "Longitude"
    Car:
      type: object
      required: [position, title, sipp_code, category, transmission, seats, bags, thumbnail, offers]
      properties:
        position:
          type: integer
          description: "Position of the car in Skyscanner's order"
        title:
          type: string
          description: "Model Skyscanner shows for the car, such as Toyota Yaris"
        sipp_code:
          type: string
          description: "Industry code for the car's class, type, transmission and air conditioning, such as EDAR"
        category:
          type: string
          description: "Size class of the car, such as economy, compact, intermediate or fullsize"
        transmission:
          type: string
          description: "Transmission of the car, such as automatic or manual"
        seats:
          type: integer
          description: "Number of seats"
        bags:
          type: integer
          description: "Number of bags the car takes"
        fuel_type:
          type: string
          enum: ["electric", "hybrid"]
          description: "Fuel the car runs on"
        thumbnail:
          type: string
          description: "Photo of the car"
        rental_company:
          type: string
          description: "Rental company of the car's cheapest offer"
        offers:
          type: array
          items:
            $ref: '#/components/schemas/Offer'
          description: "Offers Skyscanner shows for the car, cheapest first"
    Offer:
      type: object
      required: [source, car_name, sipp_code, seats, bags, total_price, tracking_link]
      properties:
        source:
          type: string
          description: "Booking site that sells the offer, such as Expedia"
        rating:
          type: number
          description: "Rating of the booking site, out of 5"
        reviews:
          type: integer
          description: "Number of reviews behind the booking site's rating"
        car_name:
          type: string
          description: "Car as the booking site names it"
        sipp_code:
          type: string
          description: "Booking site's industry code for the car"
        seats:
          type: integer
          description: "Number of seats the booking site lists"
        bags:
          type: integer
          description: "Number of bags the booking site lists"
        has_air_conditioning:
          type: boolean
          description: "Whether the car has air conditioning"
        has_four_wheel_drive:
          type: boolean
          description: "Whether the car has four-wheel drive"
        total_price:
          $ref: '#/components/schemas/Price'
        fuel_policy:
          type: string
          description: "Fuel policy, such as full_to_full or same_to_same"
        has_unlimited_mileage:
          type: boolean
          description: "Whether the rental has no mileage limit"
        included_mileage:
          $ref: '#/components/schemas/IncludedMileage'
        has_free_cancellation:
          type: boolean
          description: "Whether the offer can be cancelled for free"
        has_collision_damage_waiver:
          type: boolean
          description: "Whether the offer includes a collision damage waiver"
        has_theft_protection:
          type: boolean
          description: "Whether the offer includes theft protection"
        has_third_party_cover:
          type: boolean
          description: "Whether the offer includes third-party liability cover"
        pickup_location:
          $ref: '#/components/schemas/PickupLocation'
        pickup_type:
          type: string
          description: "How the car is collected, such as desk_in_terminal, shuttle or meet_and_greet"
        payment_type:
          type: string
          enum: ["pay_now", "pay_partly_now", "pay_on_arrival"]
          description: "When the rental is paid"
        tracking_link:
          type: string
          description: "Skyscanner link that sends the traveller on to book with the booking site"
    Price:
      type: object
      required: [extracted_price]
      description: "Price for the whole rental"
      properties:
        extracted_price:
          type: number
          description: "Price in the search's currency"
    IncludedMileage:
      type: object
      required: [distance, unit]
      description: "Distance the rental includes before extra charges"
      properties:
        distance:
          type: integer
          description: "Distance included"
        unit:
          type: string
          description: "Unit of the distance, such as mile or km"
    PickupLocation:
      type: object
      required: [gps_coordinates]
      description: "Rental desk where the car is collected"
      properties:
        name:
          type: string
          description: "Name of the place the desk serves, such as Los Angeles International"
        address:
          type: string
          description: "Address of the desk"
        gps_coordinates:
          $ref: '#/components/schemas/GpsCoordinates'
        is_airport:
          type: boolean
          description: "Whether the desk is at an airport"
    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
          description: Error message describing what went wrong
