Booking.com Hotel Availability API: Check-In Dates, Prices, and NO DATA

Published October 17, 2026

The hotel-details request returned HTTP 200, but there was no hotel to display. Its operation payload was:

{
  "message": "NO DATA!",
  "status": false,
  "status_code": 400,
  "data": null
}

This saved negative control deliberately used the nonexistent hotel_id=999999999. It demonstrates a business failure inside a successful HTTP exchange, not that changing dates repairs a hotel lookup. For another request returning NO DATA!, the actual cause remains unknown unless additional evidence establishes it.

The useful comparison is a populated response for a known hotel, with its identity and stay context intact. All observations below are historical samples captured on October 18, 2026, not promises about today's inventory.

Route status=false to an error path even when HTTP is 200

Keep three checks separate: HTTP status, the outer gateway's code / message / data envelope, and the operation payload inside it. The inner status and status_code are not interchangeable with the outer code. A transport success must not bypass either business check.

For get-hotel-details, inspect inner status before accessing hotel fields. In the negative control, status=false and data=null mean there is no usable property object. Do not turn that into an empty hotel card, a zero-dollar price, or a definitive "sold out" label.

The positive control used hotel_id=180769. It returned status=true, message=Success, and a populated object identifying Hyatt Grand Central New York, with rooms, facilities, policies and price breakdowns. That establishes a successful historical lookup for that request, not universal coverage.

The omitted-date probe returned 2026-10-18 through 2026-10-22

The saved no-date request supplied only the hotel, currency and language:

curl 'https://api.opendata-api.com/api/project/booking/get-hotel-details?key=YOUR_API_KEY&hotel_id=180769&currency_code=USD&language_code=en-us'

Replace YOUR_API_KEY with your own authorized platform key only when you intend to run a request. Query URLs contain that key; redact it from logs and shared material. Opening this guide, following a documentation link, expanding fields or copying a snippet sends no data request. Running the command does.

The response contained arrival_date=2026-10-18 and departure_date=2026-10-22. The documented defaults are current-date check-in and checkout four days later. Those calendar values describe the probe-time default; they are not permanent defaults to hard-code.

Omitting dates therefore does not produce a date-free property price. It still selects a stay context, which changes over time. Inspect the returned dates rather than assuming the requested hotel is being priced for your intended trip.

Freeze one stay context before requesting prices

For a reproducible comparison, explicitly carry the same checkin_date, checkout_date, adults, children_age, rooms, currency_code and language_code through search and details wherever the selected route exposes them. Require checkout after check-in. For a party without children, do not invent child ages; for a family, retain the actual ages consistently. Some separate property routes also expose children; follow their own contracts rather than renaming fields.

This is the historical dated detail request for two adults and one room:

curl 'https://api.opendata-api.com/api/project/booking/get-hotel-details?key=YOUR_API_KEY&hotel_id=180769&checkin_date=2026-11-15&checkout_date=2026-11-17&adults=2&rooms=1&currency_code=USD&language_code=en-us'

These dates were valid for the saved observation. Choose valid dates deliberately for a new comparison; the sample is not evidence that this stay remains available.

Its composite_price_breakdown reported USD gross_amount.value=675.18 and gross_amount_per_night.value=337.59, alongside excluded_amount and itemized charges. Keep those fields distinct. A nightly amount is not a stay total, and a gross amount alone does not establish the final payable price. Check currency, included versus excluded taxes, occupancy and each room block's cancellation and prepayment terms before comparing offers.

Hand off the property ID without substituting the city's UFI

The validated stays-search used query=city:20088325 for New York. Its rows carried their own property id values and city ufi=20088325. A row's property id can be handed to hotel details as hotel_id; the city UFI cannot.

Hotel 180769 was a separately verified property control. Do not assume it appeared on the saved search page, and always check the returned hotel_id, hotel_name, city, address and property URL against your intended property.

Accommodation autocomplete is unavailable: the two failed accommodation-autocomplete routes were omitted. Bring independently known destination queries or hotel IDs rather than building a workflow that depends on those routes. Flight autocomplete working does not replace accommodation discovery.

The separate properties workflow uses detail_id and has its own URL-based lookups. Neither a city UFI nor that workflow's detail identifier is automatically a hotel_id. Preserve exact parameter spellings when moving between workflows, including categories_filter versus categories-filter.

Validate 20 hotel rows before paginating 549 matches

The historical New York search requested the same November 15–17 stay, two adults, one room and USD. It sent page_size=10, but returned 20 rows, with currentPage=1, resultsPerPage=20 and totalResultCount=549.

Count the actual rows and inspect returned metadata. Do not allocate a ten-row-only parser or claim the requested page size was honored. Conversely, 549 reported matches do not establish that every match can be retrieved, that later pages were tested, or that the count remains stable.

Before building pagination, validate row identities, dates and currencies on the first page. Retain property IDs for deduplication and record the request context and observation time. Check subsequent pages for overlap, changed totals and missing data; the saved evidence does not establish a complete traversal. Search-row priceBreakdown.grossPrice also needs its own price-basis check rather than inheriting every field or assumption from hotel details.

Turn NO DATA into an unresolved case, then test one input at a time

A small local classifier can keep the observed failure out of price calculations. Pass it the inner hotel payload only after separately checking HTTP status and the outer gateway envelope:

def classify_hotel_payload(payload):
    if not isinstance(payload, dict):
        return "unresolved"
    if payload.get("status") is not True:
        return "unresolved"
    hotel = payload.get("data")
    if not isinstance(hotel, dict):
        return "unresolved"
    if hotel.get("hotel_id") is None or not hotel.get("hotel_name"):
        return "unresolved"
    return "inspect_identity_and_price_context"

This code makes no request and does not diagnose the reason for failure. Keep the original business fields for investigation, with keys and private context removed.

For a new unresolved case, first verify that the identifier belongs to the intended property and workflow. Then compare against a known-property control using the same explicit dates, occupancy, currency and language. If you choose to investigate further, change one input at a time and record both request and response context. Each deliberately executed call is a new observation, not a guaranteed repair.

Changing dates on the nonexistent-ID control is not a demonstrated fix. Nor does NO DATA! alone establish sold-out inventory, a closed property, a date problem or a permanent missing listing. Preserve "unresolved" until the evidence supports something more specific.

Set boundaries around quotes, reservations, and price history

The Booking.com Hotel & Travel Data API provides read-only snapshots. A room block, quoted price, availability calendar or booking-process-information response does not reserve inventory, lock a price or take payment. URL-based POST lookups remain reads. Recheck current terms and availability before any separate booking, and respect applicable content rights.

Saved live evidence covers only hotel search, hotel details and flight autocomplete: stays-search, get-hotel-details and flights-auto-complete. The other 67 public routes were not live-tested, including dedicated room, calendar and property follow-ups, flight pricing and details, rental cars, attractions and transfers. Their behavior is documented, not proven by these fixtures.

These samples are not a historical-price feed. Build any permitted history from your own timestamped, like-for-like observations, retaining missing and unresolved states rather than filling them with invented prices. The defensible result is a price for a verified property and explicit stay context at an observation time—not a booking, a complete market inventory, or an explanation for every NO DATA! response.