Blog / API guides

Expedia Hotels API: Search Hotels and Rooms as JSON

To search Expedia hotels as JSON, call GET /v1/expedia/hotels-search with a region_id, a check-in date and a check-out date. It returns a ranked list of properties with price, guest rating and a property_id. Pass that ID to GET /v1/expedia/hotels-rooms to get each room and its rate plans. Every call costs 1 credit, and failed calls cost nothing.

Which endpoints make up the Expedia hotel search flow?

Four endpoints cover a hotel search from a typed place name to a bookable room. You look up a destination, search hotels in it for a date range, then drill into one property for rooms or detail. All four are GET requests that return JSON and cost 1 credit each. The table lists the required and optional parameters.

Endpoint Returns Required Optional
/v1/expedia/destinations Destinations query limit
/v1/expedia/hotels-search Hotels Search check_in, check_out, region_id adults, children, region_name, sort, limit, offset
/v1/expedia/hotels-rooms Hotels Rooms check_in, check_out, property_id adults, children
/v1/expedia/hotels-detail Hotels Detail property_id check_in, check_out, adults

Each endpoint has its own page with a playground: Destinations, Hotels Search, Hotels Rooms and Hotels Detail. The wider Travel APIs area lists the other travel sources in the catalogue.

How do you authenticate and make the first call?

Send your key in the X-API-Key header on every request. Keys start with sk_live_, and where a header isn't possible you can use the api_key query parameter instead. A free account gets 1,000 credits every month after you verify an email address, with no credit card, so the calls below are free to try. The authentication docs cover the details.

Start with the destination lookup. query takes up to 100 characters, and limit is optional:

curl "https://api.perceptlayer.com/v1/expedia/destinations?query=Paris&limit=5" \
  -H "X-API-Key: $API_KEY"

Run it in the playground on the Destinations page to see the response for your own query, then use the region you want as region_id in the search. The recorded searches in this article use region_id=2734 with region_name=Paris, France. If you don't have a key yet, get a free API key first.

How do you search hotels for a date range?

GET /v1/expedia/hotels-search takes a region_id, check_in and check_out, and returns a ranked list of properties for those dates. Add adults for the party size, region_name as a label (up to 120 characters), and limit and offset to page. This request asks for the first 10 hotels in Paris for two adults:

curl "https://api.perceptlayer.com/v1/expedia/hotels-search?region_id=2734&region_name=Paris%2C+France&check_in=2026-11-20&check_out=2026-11-23&adults=2&limit=10" \
  -H "X-API-Key: $API_KEY"

Parameters

Parameter Type Required Notes
check_in string yes Dates in the recorded requests look like 2026-11-20
check_out string yes Same format as check_in
region_id string yes From the destinations lookup
adults integer no Number of adults
children string no Children in the party
region_name string no Up to 120 characters
sort string no One of recommended, price_low_to_high, review
limit integer no Hotels per page
offset integer no Where the page starts

What does the response look like?

This is a recorded response for the request above, trimmed to the first hotel:

{
  "success": true,
  "data": {
    "region_id": "2734",
    "check_in": "2026-11-20",
    "check_out": "2026-11-23",
    "hotels": [
      {
        "property_id": "564660",
        "position": 1,
        "name": "Mercure Paris Centre Tour Eiffel",
        "area": "Paris",
        "guest_rating": 8,
        "guest_rating_label": "Very good",
        "review_count": 1000,
        "total_price": 690,
        "price_per_night": 230,
        "free_cancellation": false,
        "sponsored": true,
        "amenities_preview": ["restaurant", "bar"],
        "currency": "EUR"
      },
      …
    ],
    "total_results": 500,
    "offset": 0,
    "has_more": true,
    "next_offset": 10
  },
  "meta": {
    "endpoint_family": "hotel_search",
    "billable": true
  }
}

A few fields are worth knowing before you build on them. The recording shows position: 1 and sponsored: true on the hotel shown (and sponsored: true on both hotels recorded); the brief doesn't document what either field means, so check them against your own results before relying on them. The prices are in the currency field (EUR here), and total_price for this stay is price_per_night times three nights: 3 × 230 = 690. Some hotels also carry an original_price next to total_price, which shows a discount. Each hotel also has url and image_urls, left out above.

How do you page through results?

Use has_more and next_offset. The recorded response reports total_results of 500, offset of 0 and next_offset of 10 with limit=10, so the next call repeats the request with offset=10. The recording shows has_more as true; no final page is recorded, so check the last page's response yourself before you rely on its shape. Each page is a separate call at 1 credit, so reading 500 results at 10 per page is 50 calls × 1 credit = 50 credits. The request and response docs describe the response envelope.

How do you list rooms and rate plans for one hotel?

GET /v1/expedia/hotels-rooms takes a property_id from the search, the same dates, and optionally adults and children. It returns each room type with its features, amenities and a list of rate plans, each with a rate_plan_id, total_price and price_per_night. Rooms are where you see the spread within one hotel:

curl "https://api.perceptlayer.com/v1/expedia/hotels-rooms?property_id=564660&check_in=2026-11-20&check_out=2026-11-23&adults=2" \
  -H "X-API-Key: $API_KEY"

Recorded response for that request, trimmed to the first room:

{
  "success": true,
  "data": {
    "property_id": "564660",
    "check_in": "2026-11-20",
    "check_out": "2026-11-23",
    "currency": "EUR",
    "rooms": [
      {
        "unit_id": "226385",
        "name": "Classic Room, 1 Double Bed",
        "features": ["18 sq m", "Sleeps 2"],
        "highlights": ["Soundproofed rooms", "Air-conditioning"],
        "amenities": ["Wheelchair accessibility", "Bathtub or shower"],
        "rate_plans": [
          {
            "rate_plan_id": "397104173",
            "total_price": 690,
            "price_per_night": 230
          },
          {
            "rate_plan_id": "397104181",
            "total_price": 825,
            "price_per_night": 275
          }
        ]
      },
      …
    ]
  },
  "meta": {
    "endpoint_family": "room_offers",
    "billable": true
  }
}

The first rate plan, at 690 for three nights, matches the total_price the search gave for the same hotel and dates. The second room in the recorded response, "Classic Room, 2 Single Beds", has plans at 700 and 825. In this recording the search price equals the lowest rate plan of the first room, and the rooms call shows what the other plans cost.

What does the detail endpoint add?

GET /v1/expedia/hotels-detail takes a property_id and, optionally, check_in, check_out and adults. Only property_id is required. We haven't recorded a response for it, so we can't show its fields here. See the Hotels Detail page for the fields and run it in the playground with your key.

How do you chain the calls in Python?

Search first, then fetch rooms for the top results. The script uses only the parameters and fields in the recordings above, and you need API_KEY set. It searches Paris for two adults, takes the first three hotels and prints each room's rate plans:

import os
import requests

BASE = "https://api.perceptlayer.com"
HEADERS = {"X-API-Key": os.environ["API_KEY"]}
DATES = {"check_in": "2026-11-20", "check_out": "2026-11-23"}


def get(path, **params):
    r = requests.get(BASE + path, headers=HEADERS, params=params, timeout=30)
    r.raise_for_status()
    return r.json()["data"]


search = get(
    "/v1/expedia/hotels-search",
    region_id="2734",
    region_name="Paris, France",
    adults=2,
    limit=10,
    **DATES,
)

for hotel in search["hotels"][:3]:
    print(hotel["name"], hotel["total_price"], hotel["currency"])
    rooms = get(
        "/v1/expedia/hotels-rooms",
        property_id=hotel["property_id"],
        adults=2,
        **DATES,
    )
    for room in rooms["rooms"]:
        for plan in room["rate_plans"]:
            print("  ", room["name"], plan["rate_plan_id"], plan["total_price"])

This run makes 1 search and 3 rooms calls: 4 calls × 1 credit = 4 credits. Add a try around raise_for_status and read the JSON error body when it fails; the error docs list the codes. If a request times out, it may have succeeded and been billed, because requests have no idempotency key.

What does it cost to run at scale?

Every call to these endpoints costs 1 credit, so cost is the call count. Watching 50 hotels for one stay, once a day for 30 days, is 50 × 30 = 1,500 rooms calls, or 1,500 credits. That's above the 1,000 free credits you get each month, and within the smallest 10,000-credit Starter pack. Purchased credits last 12 months, with no subscription. Pricing has what credits cost.

Responses carry X-Credits-Used and X-Credits-Remaining, so you can track spend per call. Rates are per account and counted per minute: free accounts get 1 request a second, and paying accounts at least 5. A 429 response carries a Retry-After header with the seconds to wait. See rate limits and credits. For a rate-monitoring design, read hotel price data for rate monitoring.

Should you use Expedia's own API instead?

If you're a travel partner of Expedia Group, probably yes. Expedia Group runs a partner API called Rapid for lodging search and booking, and its developer support pages point to the partner support channels. Check there for current access terms. It's the natural route if you need to take bookings or want a contractual relationship with Expedia.

Perceptlayer fits a different job: reading search results as JSON without a partner agreement, for price comparison, research or an agent that needs live hotel prices. Data is collected from publicly available sources and returned as found at the time of the call. For other hotel sources, see the Booking.com guide and the Google Hotels guide.

Next step: get a free API key, then run hotels-search in the playground on the Expedia API page.

APIs in this post

Frequently asked questions

Does Expedia have a public hotel search API?

Expedia Group offers a partner API, Rapid, for lodging search and booking, aimed at travel partners. For read-only hotel search results as JSON without a partner agreement, the hotels-search endpoint on Perceptlayer takes a region, dates and party size and returns ranked properties with prices.

How much does an Expedia hotel search cost per call?

Each of the four Expedia endpoints costs 1 credit per successful call. A search plus rooms for one hotel is 2 credits. Failed calls cost nothing and return X-Credits-Used: 0. Free accounts get 1,000 credits a month, and pricing shows what credit packs cost.

How do I get the region_id for a city?

Call GET /v1/expedia/destinations with query set to the place name, for example query=Paris, and use the region you want as region_id in the search. The recorded searches in this guide use region_id=2734 for Paris, France.

Why is the search price different from a room's price?

The search returns one headline price per hotel, such as 690 for three nights in the recorded response. The rooms endpoint lists every room and rate plan for the same dates, such as 690 and 825 for one room type. Use the rooms call when you need the full spread.

What happens when the balance runs out?

The service is prepaid. When credits run out, calls return insufficient_credits with HTTP status 402 and nothing more is debited. There is no automatic top-up. Errors come back as JSON with a code, message and request_id, described in the error docs.

  1. Booking.com Hotel Prices API: Search, Rooms and Reviews

    Eleven Booking.com endpoints as JSON: search, prices, rooms and reviews, with parameters and a 1,000-hotel price check costed in credits.

  2. Trivago Hotel Prices API: Deals and Search as JSON

    Call trivago suggest, search and deals as JSON: 1 credit per call, a recorded Paris search response, and the provider_count field in a metasearch result.

  3. Booking.com Reviews API: Hotel Review Scores as JSON

    Pull Booking.com review scores and guest reviews as JSON with two GET calls at 1 credit each. Parameters, sorting, paging and the cost of covering a city.

Start with 1,000 free credits

No password to set. We email you a sign-in link, and your key works on every API.

No credit card. 1,000 free credits a month.