openapi: 3.0.0
info:
  title: Bing Maps API
  description: |
    Search Bing Maps for places such as businesses, landmarks and addresses around a location or GPS coordinates.

    A search for a kind of place returns a list in `local_results`, with each place's id, category, address, phone, website, rating, opening status and GPS coordinates. When Bing Maps answers with a single place, such as a landmark, a business or an address, the response carries that place in `place_result`, with its weekly hours, description, photos and ratings on review sites when Bing Maps has them.

    **Location**: set `location`, or `lat` and `lon`, to choose where the map is centered. Without them, the map is centered on a major city of the country set by `market_code` or `country_code`. When nothing matches near the center, Bing Maps can return places far from it: compare their `gps_coordinates` with the center.

    **Filters**: searches for some kinds of places, such as restaurants and hotels, return a `filters` block with rating, opening hours, hotel class or cuisine options. Pass option `value`s, one per filter group and separated by commas, as the `filters` parameter of a new search. Values are case-sensitive, and Bing Maps ignores a value it does not offer for the search. Rating filters are approximate: a place's `rating` from a review site can be slightly below the chosen stars.

    **Pagination**: `page` goes up to `floor(60 / num) + 1`, which is page 4 with the default `num` of 20. Bing's ranking varies between requests, so a place can appear on more than one page. De-duplicate results on `place_id`. A page that `pagination.next` offers can have no more places.

    **Language**: text such as `type`, `hours`, `open_hours` and filter labels follows `language`, else `market_code`.
  version: 1.0.0
servers:
  - url: https://www.searchapi.io/api/v1
paths:
  /search:
    get:
      summary: Bing Maps Search
      security:
        - ApiKeyAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: engine
          in: query
          required: true
          description: 'Search engine. Must be set to: `bing_maps`'
          schema:
            type: string
            enum: ["bing_maps"]
        - name: q
          in: query
          required: true
          description: Search query, such as a kind of place (`coffee`), a business name, a landmark or an address. Accented and non-Latin characters take more room, so fewer fit, such as 388 Chinese, Japanese or Korean characters. When Bing Maps answers with a single place, the response carries `place_result` instead of `local_results`.
          schema:
            type: string
            maxLength: 1000
        - name: location
          in: query
          required: false
          description: Name of the place to center the map on, such as `New York,New York,United States`. If several locations match, the most popular one is selected. Head to the Locations API for exact names. Can't be used together with `lat` and `lon`.
          schema:
            type: string
            maxLength: 200
        - name: lat
          in: query
          required: false
          description: Latitude of the map center in decimal degrees. Must be used together with `lon`, and can't be used together with `location`.
          schema:
            type: number
            minimum: -85
            maximum: 85
        - name: lon
          in: query
          required: false
          description: Longitude of the map center in decimal degrees. Must be used together with `lat`, and can't be used together with `location`.
          schema:
            type: number
            minimum: -180
            maximum: 180
        - name: market_code
          in: query
          required: false
          description: Bing market in `language-country` format, which sets the country of the search and the language of text in the results. When set, `country_code` is ignored.
          schema:
            type: string
            enum: ["es-ar", "en-au", "de-at", "nl-be", "fr-be", "pt-br", "en-ca", "fr-ca", "es-cl", "da-dk", "fi-fi", "fr-fr", "de-de", "zh-hk", "en-in", "en-id", "it-it", "ja-jp", "ko-kr", "en-my", "es-mx", "nl-nl", "en-nz", "no-no", "zh-cn", "pl-pl", "en-ph", "ru-ru", "en-za", "es-es", "sv-se", "fr-ch", "de-ch", "zh-tw", "tr-tr", "en-gb", "en-us", "es-us"]
        - name: country_code
          in: query
          required: false
          description: Country of the search when `market_code` is not set.
          schema:
            type: string
            enum: ["AR", "AU", "AT", "BE", "BR", "CA", "CL", "DK", "FI", "FR", "DE", "HK", "IN", "ID", "IT", "JP", "KR", "MY", "MX", "NL", "NZ", "NO", "PL", "PT", "PH", "RU", "SA", "ZA", "ES", "SE", "CH", "TW", "TR", "GB", "US", "CN"]
            default: "US"
        - name: language
          in: query
          required: false
          description: Language of text in the results, such as categories, opening hours and filter labels. Takes precedence over the language of `market_code`.
          schema:
            type: string
            enum: ["ar", "eu", "bn", "bg", "ca", "zh-hans", "zh-hant", "hr", "cs", "da", "nl", "en", "en-gb", "et", "fi", "fr", "gl", "de", "gu", "he", "hi", "hu", "is", "it", "ja", "jp", "kn", "ko", "lv", "lt", "ms", "ml", "mr", "nb", "pl", "pt-br", "pt-pt", "pa", "ro", "ru", "sr", "sk", "sl", "es", "sv", "ta", "te", "th", "tr", "uk", "vi"]
        - name: filters
          in: query
          required: false
          description: Up to 3 filter values, one per filter group, separated by commas, such as `ONow,UR8U`. Take them from `filters[].options[].value` in a previous response; values are case-sensitive.
          schema:
            type: string
            pattern: '^(UR[A-Za-z0-9_]{1,14}|O[A-Za-z0-9_]{1,15}|HC[A-Za-z0-9_]{1,14}|CC_[A-Za-z0-9_]{1,13})(,(UR[A-Za-z0-9_]{1,14}|O[A-Za-z0-9_]{1,15}|HC[A-Za-z0-9_]{1,14}|CC_[A-Za-z0-9_]{1,13})){0,2}$'
        - name: num
          in: query
          required: false
          description: Maximum number of results per page.
          schema:
            type: integer
            minimum: 3
            maximum: 25
            default: 20
        - name: page
          in: query
          required: false
          description: Page number, from 1 to `floor(60 / num) + 1`, which is page 4 with the default `num` of 20.
          schema:
            type: integer
            minimum: 1
            maximum: 21
            default: 1
      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'
        local_results:
          type: array
          items:
            $ref: '#/components/schemas/LocalResult'
          description: "Places on this page, in Bing Maps' order"
        place_result:
          $ref: '#/components/schemas/PlaceResult'
        filters:
          type: array
          items:
            $ref: '#/components/schemas/Filter'
          description: "Filters Bing Maps offers for the search"
        pagination:
          $ref: '#/components/schemas/Pagination'
        error:
          type: string
          description: "Error message returned instead of results, such as when Bing Maps finds no places or has no more results for the requested page"
    SearchMetadata:
      type: object
      required: [id, 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: "Bing Maps URL for this search"
        html_url:
          type: string
          description: "URL to view HTML results"
        json_url:
          type: string
          description: "URL to view JSON results"
    SearchParameters:
      type: object
      properties:
        engine:
          type: string
          description: "Search engine used"
        q:
          type: string
          description: "Search query"
        location:
          type: string
          description: "Location the map is centered on"
        location_used:
          type: string
          description: "Canonical name of the location the map is centered on"
        lat:
          type: string
          description: "Latitude the map is centered on"
        lon:
          type: string
          description: "Longitude the map is centered on"
        market_code:
          type: string
          description: "Bing market used"
        country_code:
          type: string
          description: "Country used"
        language:
          type: string
          description: "Language used"
        filters:
          type: string
          description: "Filter values requested"
        num:
          type: string
          description: "Maximum number of results per page"
        page:
          type: string
          description: "Page number"
    SearchInformation:
      type: object
      properties:
        query_displayed:
          type: string
          description: "Query Bing Maps searched for"
        showing_results_for:
          type: string
          description: "Spelling correction Bing Maps searched for instead of the query"
    Place:
      type: object
      properties:
        place_id:
          type: string
          description: "Bing Maps id of the place"
        title:
          type: string
          description: "Name of the place"
        link:
          type: string
          description: "Bing Maps link to the place"
        type:
          type: string
          description: "Main category of the place"
        type_id:
          type: string
          description: "Bing id of the main category, the last id in `type_path`"
        type_path:
          type: string
          description: "Bing category ids separated by dots, from the broadest category to `type_id`"
        address:
          type: string
          description: "Address of the place"
        phone:
          type: string
          description: "Phone number of the place"
        website:
          type: string
          description: "Website of the place"
        rating:
          type: number
          description: "Average rating out of 5, which Bing Maps converts from sites that rate out of 10"
        reviews:
          type: integer
          description: "Number of reviews behind the rating"
        reviews_source:
          type: string
          description: "Site the rating and reviews come from, such as Yelp or Tripadvisor"
        open_state:
          type: string
          enum: ["open", "closed", "changing_soon"]
          description: "Open status of the place when the search ran, with `changing_soon` when it opens or closes soon"
        hours:
          type: string
          description: "Opening status line as Bing Maps shows it, such as `Open · Closes 6 PM`"
        gps_coordinates:
          $ref: '#/components/schemas/GpsCoordinates'
        thumbnail:
          type: string
          description: "Image of the place"
        chain_id:
          type: string
          description: "Bing id of the chain the place belongs to"
        hotel_class:
          type: string
          description: "Hotel class as Bing Maps shows it, such as `4-star hotel`"
        extracted_hotel_class:
          type: integer
          description: "Number of stars in `hotel_class`"
        is_permanently_closed:
          type: boolean
          description: "Whether the place is permanently closed"
        amenities:
          type: array
          items:
            type: string
          description: "Amenities of the place, such as `Free parking`"
    LocalResult:
      allOf:
        - type: object
          required: [position, place_id, title, link, gps_coordinates]
          properties:
            position:
              type: integer
              description: "Position of the place on this page, starting at 1"
        - $ref: '#/components/schemas/Place'
    PlaceResult:
      allOf:
        - $ref: '#/components/schemas/Place'
        - type: object
          required: [title, gps_coordinates]
          properties:
            open_hours:
              type: array
              items:
                $ref: '#/components/schemas/OpenHours'
              description: "Opening hours for each day of the week, starting with today"
            is_claimed:
              type: boolean
              description: "Whether the business has claimed its Bing listing"
            description:
              type: string
              description: "Description of the place"
            images:
              type: array
              items:
                $ref: '#/components/schemas/Image'
              description: "Photos of the place"
            web_reviews:
              type: array
              items:
                $ref: '#/components/schemas/WebReview'
              description: "Ratings of the place on review sites"
            bounds:
              $ref: '#/components/schemas/Bounds'
    GpsCoordinates:
      type: object
      required: [latitude, longitude]
      properties:
        latitude:
          type: number
          description: "Latitude of the place"
        longitude:
          type: number
          description: "Longitude of the place"
    Bounds:
      type: object
      description: "Extent of a geocoded area, such as a city or an address"
      required: [north_latitude, west_longitude, south_latitude, east_longitude]
      properties:
        north_latitude:
          type: number
          description: "Latitude of the northern edge"
        west_longitude:
          type: number
          description: "Longitude of the western edge"
        south_latitude:
          type: number
          description: "Latitude of the southern edge"
        east_longitude:
          type: number
          description: "Longitude of the eastern edge"
    OpenHours:
      type: object
      required: [day, hours]
      properties:
        day:
          type: string
          description: "Day of the week"
        hours:
          type: string
          description: "Opening hours on that day, with several time ranges separated by commas"
    Image:
      type: object
      required: [thumbnail]
      properties:
        thumbnail:
          type: string
          description: "Bing thumbnail of the photo"
        original:
          type: string
          description: "Link to the full-size photo on the site it comes from"
    WebReview:
      type: object
      required: [name]
      properties:
        name:
          type: string
          description: "Name of the review site, such as Tripadvisor"
        rating:
          type: number
          description: "Rating of the place on the site's own scale"
        max_rating:
          type: integer
          enum: [5, 10]
          description: "Highest rating on the site's scale"
        reviews:
          type: integer
          description: "Number of reviews of the place on the site"
        link:
          type: string
          description: "Link to the place's reviews on the site"
        reviews_histogram:
          $ref: '#/components/schemas/ReviewsHistogram'
        review_results:
          type: array
          items:
            $ref: '#/components/schemas/ReviewResult'
          description: "Recent reviews from the site"
    ReviewsHistogram:
      type: object
      description: "Number of reviews for each star rating in Bing Maps' rating snapshot, a sample that changes with `language`"
      properties:
        "1":
          type: integer
          description: "Number of 1-star reviews"
        "2":
          type: integer
          description: "Number of 2-star reviews"
        "3":
          type: integer
          description: "Number of 3-star reviews"
        "4":
          type: integer
          description: "Number of 4-star reviews"
        "5":
          type: integer
          description: "Number of 5-star reviews"
    ReviewResult:
      type: object
      properties:
        username:
          type: string
          description: "Name of the reviewer"
        rating:
          type: number
          description: "Rating the reviewer gave, out of 5"
        description:
          type: string
          description: "Text of the review as Bing Maps shows it"
        date:
          type: string
          description: "Date of the review as Bing Maps shows it"
        link:
          type: string
          description: "Link to the full review"
    Filter:
      type: object
      required: [key, options]
      properties:
        key:
          type: string
          enum: ["rating", "open_time", "hotel_class", "cuisine"]
          description: "Filter group, the same in every language"
        type:
          type: string
          description: "Label of the filter group as Bing Maps shows it"
        options:
          type: array
          items:
            $ref: '#/components/schemas/FilterOption'
          description: "Options of the filter group"
    FilterOption:
      type: object
      required: [value]
      properties:
        text:
          type: string
          description: "Label of the option as Bing Maps shows it"
        value:
          type: string
          description: "Value to pass in the `filters` parameter to apply the option"
        is_selected:
          type: boolean
          description: "Whether the option is applied to this search"
    Pagination:
      type: object
      required: [current]
      properties:
        current:
          type: integer
          description: "Current page number"
        next:
          type: integer
          description: "Next page number to pass as `page`"
    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
          description: Error message describing what went wrong
