Booking.com hotel prices for the dates you actually asked for
The Booking.com API returns hotel search, prices and availability as clean JSON.
5 active endpoints, on 1, 2 and 3 credit tiers.
- POST/booking/v1/hotels/search
- POST/booking/v1/hotels/detail
- POST/booking/v1/hotels/availability
- POST/booking/v1/hotels/reviews
- POST/booking/v1/destinations/autocomplete
What Booking.com endpoints does ReefAPI ship?
5 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.
Booking.com API
3 of 5 endpoints, ready to run
Twenty-five hotels a page for one destination and one date range, each with the stay total, the review score and the room configuration. The dates are not decoration — the same search without them came back empty.
{ "ok": true, "meta": { "api": "booking", "endpoint": "hotels/search", "mode": "live", "latency_ms": 19090.5, "record_count": 25, "cache_hit": false, "completeness_pct": 100 }, "data": { "items": [ { "hotel_id": 13687655, "page_name": "dalma-baixa", "name": "Dalma Baixa", "description": null, "url": "https://www.booking.com/hotel/pt/dalma-baixa.html", "location": { "address": "Rua da Conceição 11-13", "city": "Lisboa", "country_code": "pt", "latitude": null, "longitude": null, "display": "Santa Maria Maior, Lisbon", "distance": "0.3 miles from downtown", "geo_distance_meters": null }, "price": { "text": "Total", "amount": "€ 247.93", "amount_rounded": "€ 248", "amount_unformatted": 247.934, "currency": "EUR" }, "price_before_discount": { "text": null, "amount": "", "amount_rounded": "", "amount_unformatted": 0, "currency": "" }, "charges_info": null, "excluded_charges": { "__typename": "ExcludeChargesIrene", "excludeChargesAggregated": { "__typename": "PriceDisplayAggregatedIrene", "copy": { "translation": null, "__typename": "TranslationTag" }, "amountPerStay": { "amount": "€ 30.88", "__typename": "PriceDisplayIrene", "amountUnformatted": 30.8760000000001, "amountRounded": "€ 31", "currency": "EUR" } }, "excludeChargesList": [ { "amountPerStay": { "amount": "€ 16", "__typename": "PriceDisplayIrene", "amountUnformatted": 16.0000000000001, "amountRounded": "€ 16", "currency": "EUR" }, "__typename": "ChargeDisplayIrene", "chargeType": 22, "chargeInclusion": "EXCLUDED", "chargeMode": "PER_PERSON_PER_NIGHT" }, { "chargeInclusion": "INCLUDED", "chargeMode": "PERCENTAGE", "__typename": "ChargeDisplayIrene", "amountPerStay": { "amount": "€ 14.88", "__typename": "PriceDisplayIrene", "amountUnformatted": 14.8760000000001, "amountRounded": "€ 15", "currency": "EUR" }, "chargeType": 21 } ] }, "discounts": [], "meal_plan": null, "breakfast_included": false, "review_score": { "score": 9, "review_count": 412, "label": "Wonderful", "secondary_score": 9.8 }, "star_rating": 3, "accommodation_type_id": 204, "photo": "/xdata/images/hotel/square600/727495058.jpg?k=657475be667fc786ee5f25ce9dddffaa60086337667c89d5bbfeb541db60cb96&o=", "room_configurations": { "commonConfiguration": { "__typename": "UnitConfiguration", "localizedArea": null, "bedConfigurations": [ { "__typename": "BedConfiguration", "nbAllBeds": 1, "beds": [ { "count": 1, "__typename": "Bed", "type": 6 } ] } ], "name": null, "nbBedrooms": 0, "nbKitchens": 0, "nbAllBeds": 1, "nbUnits": 1, "nbLivingrooms": 0, "nbBathrooms": 0, "unitId": 0, "unitTypeNames": [] }, "__typename": "MatchingUnitConfigurations", "unitConfigurations": [ { "nbBathrooms": 0, "apartmentRooms": [], "unitId": 1368765501, "unitTypeNames": [], "localizedArea": null, "__typename": "UnitConfiguration", "bedConfigurations": [ { "nbAllBeds": 1, "beds": [ { "type": 6, "__typename": "Bed", "count": 1 } ], "__typename": "BedConfiguration" } ], "nbBedrooms": 0, "name": "Interior Double Room", "unitTypeId": 9, "nbKitchens": 0, "nbAllBeds": 1, "nbLivingrooms": 0, "nbUnits": 1 } ] }, "room_blocks": [ { "room_id": "1368765501", "occupancy": 2, "policy_group_id": "409108971", "package_id": "0", "meal_plan_id": 2, "final_price": { "amount": 247.934, "currency": "EUR" }, "original_price": { "amount": 247.934, "currency": "EUR" }, "free_cancellation_until": null, "cancellation_type": null, "only_left_message": "We have 1 left at this price", "available_count_hint": null, "meal_plan": null, "breakfast_included": false, "taxes_and_charges": [] } ], "policies": { "showFreeCancellation": false, "__typename": "Policies", "showNoPrepayment": false, "enableJapaneseUsersSpecialCase": null }, "badges": { "showSkiToDoor": false, "__typename": "CustomBadges", "showBhTravelCreditBadge": false, "showOnlineCheckinBadge": null } }, { "hotel_id": 8299193, "page_name": "cais-urban-lodge-lisboa12345", "name": "Cais Urban Lodge", "description": null, "url": "https://www.booking.com/hotel/pt/cais-urban-lodge-lisboa12345.html", "location": { "address": "Rua do Ferragial, 31 A", "city": "Lisboa", "country_code": "pt", "latitude": null, "longitude": null, "display": "Misericordia, Lisbon", "distance": "0.5 miles from downtown", "geo_distance_meters": null }, "price": { "text": "Total", "amount": "€ 252.69", "amount_rounded": "€ 253", "amount_unformatted": 252.6876183776, "currency": "EUR" }, "price_before_discount": { "text": null, "amount": "", "amount_rounded": "", "amount_unformatted": 0, "currency": "" }, "charges_info": null, "excluded_charges": { "__typename": "ExcludeChargesIrene", "excludeChargesAggregated": { "__typename": "PriceDisplayAggregatedIrene", "copy": { "translation": null, "__typename": "TranslationTag" }, "amountPerStay": { "__typename": "PriceDisplayIrene", "amount": "€ 14.20", "currency": "EUR", "amountRounded": "€ 14", "amountUnformatted": 14.2023012368001 } }, "excludeChargesList": [ { "chargeMode": "PER_STAY", "chargeInclusion": "INCLUDED", "chargeType": 21, "__typename": "ChargeDisplayIrene", "amountPerStay": { "amountRounded": "€ 14", "amountUnformatted": 14.2023012368001, "currency": "EUR", "amount": "€ 14.20", "__typename": "PriceDisplayIrene" } } ] }, "discounts": [], "meal_plan": null, "breakfast_included": false, "review_score": { "score": 8.7, "review_count": 1527, "label": "Excellent", "secondary_score": 9.4 }, "star_rating": 4, "accommodation_type_id": 219, "photo": "/xdata/images/hotel/square600/357060750.jpg?k=d470c88f87061a98ac49666afb7a5cefdb8102f7618299e879589e828260af7a&o=", "room_configurations": { "unitConfigurations": [ { "unitTypeId": 9, "name": "Double Room", "nbBedrooms": 0, "nbKitchens": 0, "__typename": "UnitConfiguration", "localizedArea": null, "bedConfigurations": [ { "__typename": "BedConfiguration", "nbAllBeds": 1, "beds": [ { "count": 1, "__typename": "Bed", "type": 6 } ] } ], "nbUnits": 1, "nbLivingrooms": 0, "nbAllBeds": 1, "apartmentRooms": [], "nbBathrooms": 0, "unitTypeNames": [], "unitId": 829919311 } ], "__typename": "MatchingUnitConfigurations", "commonConfiguration": { "nbBathrooms": 0, "unitId": 0, "unitTypeNames": [], "bedConfigurations": [ { "__typename": "BedConfiguration", "nbAllBeds": 1, "beds": [ { "__typename": "Bed", "type": 6, "count": 1 } ] } ], "localizedArea": null, "__typename": "UnitConfiguration", "nbKitchens": 0, "name": null, "nbBedrooms": 0, "nbAllBeds": 1, "nbUnits": 1, "nbLivingrooms": 0 } }, "room_blocks": [ { "room_id": "829919311", "occupancy": 2, "policy_group_id": "0", "package_id": "0", "meal_plan_id": 0, "final_price": { "amount": 252.6876183776, "currency": "EUR" }, "original_price": { "amount": 252.6876183776, "currency": "EUR" }, "free_cancellation_until": null, "cancellation_type": null, "only_left_message": null, "available_count_hint": null, "meal_plan": null, "breakfast_included": false, "taxes_and_charges": [] } ], "policies": { "__typename": "Policies", "enableJapaneseUsersSpecialCase": null, "showNoPrepayment": false, "showFreeCancellation": false }, "badges": { "showBhTravelCreditBadge": false, "__typename": "CustomBadges", "showSkiToDoor": false, "showOnlineCheckinBadge": null } }, { "hotel_id": 16392729, "page_name": "ouro-rossio", "name": "Ouro Rossio Hotel", "description": null, "url": "https://www.booking.com/hotel/pt/ouro-rossio.html", "location": { "address": "Rua dos Sapateiros, 213", "city": "Lisboa", "country_code": "pt", "latitude": null, "longitude": null, "display": "Santa Maria Maior, Lisbon", "distance": "450 feet from downtown", "geo_distance_meters": null }, "price": { "text": "Total", "amount": "€ 335.46", "amount_rounded": "€ 335", "amount_unformatted": 335.4623, "currency": "EUR" }, "price_before_discount": { "text": null, "amount": "", "amount_rounded": "", "amount_unformatted": 0, "currency": "" }, "charges_info": null, "excluded_charges": { "excludeChargesList": [ { "chargeMode": "PER_PERSON_PER_NIGHT", "chargeInclusion": "EXCLUDED", "chargeType": 22, "amountPerStay": { "amountRounded": "€ 16", "amountUnformatted": 16.0000000000001, "currency": "EUR", "amount": "€ 16", "__typename": "PriceDisplayIrene" }, "__typename": "ChargeDisplayIrene" }, { "chargeMode": "PERCENTAGE", "chargeInclusion": "INCLUDED", "chargeType": 21, "__typename": "ChargeDisplayIrene", "amountPerStay": { "amountUnformatted": 20.1277000000001, "amountRounded": "€ 20", "currency": "EUR", "amount": "€ 20.13", "__typename": "PriceDisplayIrene" } } ], "excludeChargesAggregated": { "copy": { "translation": null, "__typename": "TranslationTag" }, "amountPerStay": { "amountUnformatted": 36.1277000000001, "amountRounded": "€ 36", "currency": "EUR", "amount": "€ 36.13", "__typename": "PriceDisplayIrene" }, "__typename": "PriceDisplayAggregatedIrene" }, "__typename": "ExcludeChargesIrene" }, "discounts": [], "meal_plan": null, "breakfast_included": false, "review_score": { "score": 9.4, "review_count": 535, "label": "Wonderful", "secondary_score": 9.9 }, "star_rating": 3, "accommodation_type_id": 204, "photo": "/xdata/images/hotel/square600/898047865.jpg?k=a4e15fccf20d63686602f49c5ab0274cc29527e208dce12b3f6bd1f1ea1b2a80&o=", "room_configurations": { "commonConfiguration": { "localizedArea": null, "__typename": "UnitConfiguration", "bedConfigurations": [ { "nbAllBeds": 1, "beds": [ { "count": 1, "__typename": "Bed", "type": 2 } ], "__typename": "BedConfiguration" }, { "__typename": "BedConfiguration", "nbAllBeds": 2, "beds": [ { "count": 2, "type": 1, "__typename": "Bed" } ] } ], "nbBedrooms": 0, "name": null, "nbKitchens": 0, "nbAllBeds": 2, "nbLivingrooms": 0, "nbUnits": 1, "nbBathrooms": 0, "unitId": 0, "unitTypeNames": [] }, "__typename": "MatchingUnitConfigurations", "unitConfigurations": [ { "nbBathrooms": 0, "apartmentRooms": [], "unitId": 1639272901, "unitTypeNames": [], "bedConfigurations": [ { "nbAllBeds": 1, "beds": [ { "count": 1, "__typename": "Bed", "type": 2 } ], "__typename": "BedConfiguration" }, { "nbAllBeds": 2, "beds": [ { "count": 2, "__typename": "Bed", "type": 1 } ], "__typename": "BedConfiguration" } ], "__typename": "UnitConfiguration", "localizedArea": null, "nbKitchens": 0, "nbBedrooms": 0, "name": "Standard Double or Twin Room", "unitTypeId": 24, "nbAllBeds": 1, "nbLivingrooms": 0, "nbUnits": 1 } ] }, "room_blocks": [ { "room_id": "1639272901", "occupancy": 2, "policy_group_id": "434298810", "package_id": "0", "meal_plan_id": 2, "final_price": { "amount": 335.4623, "currency": "EUR" }, "original_price": { "amount": 335.4623, "currency": "EUR" }, "free_cancellation_until": "2027-04-01T23:00:00Z", "cancellation_type": null, "only_left_message": null, "available_count_hint": null, "meal_plan": null, "breakfast_included": false, "taxes_and_charges": [] } ], "policies": { "__typename": "Policies", "showNoPrepayment": false, "enableJapaneseUsersSpecialCase": null, "showFreeCancellation": true }, "badges": { "showSkiToDoor": false, "__typename": "CustomBadges", "showBhTravelCreditBadge": false, "showOnlineCheckinBadge": null } } ], "count": 25, "pagination": { "per_page": 25, "total": 2234, "offset": 0, "page": 1, "has_more": true, "next_page": 2 }, "applied": { "sort_by": "top_picks", "filters": [] } } }
How the Booking.com API works
Booking.com is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.
No OAuth app, no request signing, no per-site account. One key covers all 185 engines.
Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.
Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.
One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.
Resolve the place, price the dates, then read what the guests said
Four calls, in the order they depend on each other. The numbers below were measured while writing this, against Lisbon and a two-night September stay.
{"query": "Lisbon"}Ten suggestions in under a second, each with a dest_id, a dest_type and the source's own inventory count — 8,300 properties for the city. Keep dest_id and dest_type to skip the free-text lookup on every later call.
{"query": "Lisbon", "checkin": "2026-09-18", "checkout": "2026-09-20", "adults": 2, "currency": "EUR"}Twenty-five hotels in 1.2 seconds, and pagination.total said 1,802 — not the 8,300 the destination holds, because a dated search is an availability question. Keep page_name and country_code from any row you care about.
{"query": "Lisbon", "checkin": "...", "checkout": "...", "hotel_id": 8364648}The visible room blocks for that one hotel: room id, final price, meal plan, cancellation type and a scarcity hint. The response labels itself — visible public search inventory, not a real occupancy claim.
{"page_name": "ponto-alto", "country_code": "pt", "max_reviews": 60, "sort_by": "newest"}Sixty reviews from three internal pages, spanning six weeks back to the morning it ran, with zero duplicates to remove. Omit max_reviews and it keeps going to the end.
A priced shortlist for one date range, the room-level detail behind the one you want, and the reviews that decide whether the number is worth paying.
curl -X POST https://api.reefapi.com/booking/v1/hotels/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"dest_id":"-755070","dest_type":"city","checkin":"2026-09-18","checkout":"2026-09-20"}'{
"ok": true,
"data": { … },
"meta": {
"api": "booking",
"endpoint": "hotels/search",
"mode": "live",
"latency_ms": …,
"record_count": …
},
"error": null
}Booking.com ids, price semantics and the two rating scales
Two things bite people here: the price is the total for the stay rather than a nightly rate, and a property carries two independent scores. Booking also has a numeric hotel_id and a URL slug that do not always agree with each other. Everything below was measured on 2026-08-27 with a Paris search for 2026-09-16 to 2026-09-18, two adults, one room, currency USD.
| Field | Measured example | What it means |
|---|---|---|
| hotel_id | 7833434 | The numeric property id. Stable, and the field to join on. |
| page_name | celine-taxim | The URL slug. hotels/detail and hotels/reviews take it together with country_code. |
| room_blocks[].room_id | 783343401 | The hotel_id with a two-digit room index appended. 237896 produced 23789607, 7833434 produced 783343401. |
| price.text | "Total" | price.amount_unformatted (374.743686913343) is the total for the whole stay, not a nightly rate. |
| price_before_discount.text | "US$176.08 x 2 nights" | This is where the per-night figure appears, when a discount exists. |
| room_blocks[].original_price | 321.7927 EUR | The property's own currency. final_price (374.74 USD) is the same room converted into the currency you asked for. |
| excluded_charges aggregate | 52.84 USD per stay | Taxes and fees not inside price. Each line carries chargeInclusion INCLUDED or EXCLUDED and a chargeMode such as PER_PERSON_PER_NIGHT or PERCENTAGE. |
| review_score.score | 8.9 | Guest score out of 10, one decimal, with review_count 573 and label "Excellent". |
| star_rating | 4.0 | Official stars, 1 to 5. A different number from the review score, and null on many apartments. |
| dest_type | city, district, landmark, airport, region, hotel | All six were returned live by destinations/autocomplete. |
| dest_id for a city | -1456928 (Paris), -755070 (Istanbul) | Frequently negative. Send the minus sign, it is part of the id. |
| coordinates.latitude / longitude | null | Null in both search rows and hotels/detail. Coordinates do come back on destinations/autocomplete suggestions. |
page_name is a legacy slug, not a name. Measured: page_name le-grand-gite-de-la-doye resolves to hotel_id 6929456, "Residence du Louvre", 1 Rue de Rohan, Paris. Booking keeps the original slug when a property is relisted or renamed, so treat page_name as the address of the page and hotel_id as the identity of the property.
What moves the price, what the number includes, and where the walk really stops
Measured on 2026-08-28 against Lisbon, two date windows, two occupancies and two currencies. Three of these lines go against us.
Against us. checkin and checkout are marked optional, and a search that omits them does not fall back to a default window — it came back with zero records and an error saying the destination had resolved but returned nothing. Booking is the one engine in this category that refuses to guess a date, which is the honest behaviour and also a trap if you read the schema and not this line. Always send both.
Two nights in September against two nights in November, same city, same occupancy, same currency: exactly one of the twenty-five hotels appeared in both result sets, and that one moved from €333 to €185. The date is not a filter applied to a fixed list — it selects the list.
Two adults against four on the identical dates: two of twenty-five hotels survived into both, and both cost more with four — €127.75 became €207.70, and €162.00 became €261.00. If you are tracking a price over time, hold adults and rooms fixed, or you are measuring your own parameters.
Two identical searches minutes apart returned twenty-one hotels in common, and the price was identical on all twenty-one; the other four rows were properties that rotated in and out of the top twenty-five. A price you read is a price you can quote — but a row's POSITION is not stable, so key your diffs on hotel_id and never on rank.
Every row carries price.text 'Total' and charges_info 'Includes taxes and fees' — twenty-five of twenty-five. Beside it, price_before_discount spells out the arithmetic ('€235.70 × 2 nights') and any discount is itemised with its own name and amount. But read excluded_charges rather than the charges_info label, because the two are not the same claim: it came back empty on every Lisbon row, and the field reference above this section shows a stay where it carried 52.84 per stay of tax and fees sitting OUTSIDE the total, each line tagged INCLUDED or EXCLUDED with its own charge mode. The label is the source's summary; the block is the arithmetic.
currency prices the entire response and the conversion is the source's own — the same hotel on the same dates was €334.78 and $389.88. Both the formatted string and a raw amount_unformatted come back, so nothing has to parse a symbol.
Against us. Twenty-five a page, and the middle pages are genuinely distinct — page 1 and page 20 shared nothing at all. But page 72 and page 73 returned the same twenty-five hotels, and page 80, whose offset is past the reported total, still returned twenty-five rows instead of an empty list. Stop on pagination.has_more, which did correctly flip to false, and dedupe on hotel_id. The total drifts too: 1,802, 1,803 and 1,804 across three calls minutes apart.
The room-block action returns a note inside the payload reading 'Visible public search inventory/prices only; not a real occupancy claim'. That is the right claim to make. A block carries its price, meal plan, cancellation type and the source's own 'we have 3 left at this price' hint, and none of that is a statement about the hotel's real remaining rooms.
Against us. hotels/detail took 15 seconds, and answered with a gateway error once before it answered properly — budget for it and retry. What it returns is the static record: the rating breakdown, forty-five facility groups, fourteen room types with sizes and bed configurations, the surrounding landmarks and an FAQ. Not one price among them, and the property's own coordinates came back null even though each landmark around it carries its own.
Public hotel listings, public prices for dates you name, the publicly visible room blocks, and public guest reviews with the reviewer's country, traveller type, room type and stay dates. Not a booking, not inventory held for you, nothing behind a member-rate login, and no path to make a reservation. This reads the public board; it does not transact on it.
What people build with Booking.com
The jobs this data is most often used for.
endpoints
credits per call
Travel apps call hotels/search to show live hotel prices and availability for a destination.
Rate-parity and pricing tools use hotels/availability to monitor a property's prices across dates.
Hospitality analytics use hotels/reviews to track guest ratings and feedback.
What Booking.com data costs
The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.
Full pricing →- 1,000 free credits on signup, no card
- One key, all 185 APIs, one credit pool
- Failed and blocked calls are never charged
- Credits roll over and never expire
Call it in two lines
Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.
curl -X POST https://api.reefapi.com/booking/v1/hotels/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"dest_id":"-755070","dest_type":"city","checkin":"2026-09-18","checkout":"2026-09-20"}'import requests
r = requests.post(
"https://api.reefapi.com/booking/v1/hotels/search",
headers={"x-api-key": REEF_KEY},
json={
"dest_id": "-755070",
"dest_type": "city",
"checkin": "2026-09-18",
"checkout": "2026-09-20"
},
)
print(r.json()["data"])Have a question? We got answers.
The questions people actually ask before wiring up Booking.com.
Get a free key →Is the Booking.com price per night or for the whole stay?▾
For the whole stay. On a two-night Paris search the price block came back with text "Total", amount "$374.74" and amount_unformatted 374.743686913343. The nightly figure only appears as free text inside price_before_discount.text, for example "US$176.08 x 2 nights". If you need a nightly rate, divide by the number of nights between your checkin and checkout dates yourself. Dates are plain YYYY-MM-DD.
Are taxes and fees included in that price?▾
Partly, and the response tells you which. excluded_charges.excludeChargesList holds one entry per charge, each with chargeInclusion set to INCLUDED or EXCLUDED and a chargeMode such as PER_PERSON_PER_NIGHT or PERCENTAGE. On the measured $374.74 stay, one charge of $40.73 was INCLUDED and one of $12.11 was EXCLUDED, and the aggregated amountPerStay reported $52.84 as the total not covered by the headline price. Add that aggregate if you want the walk-up cost.
What scale is the Booking.com review score, and how does it differ from the star rating?▾
review_score.score is a guest score out of 10 with one decimal, delivered with review_count and a label. Measured: 8.9 over 573 reviews labelled "Excellent", and 7.9 over 2,055 labelled "Good". star_rating is the official star classification from 1 to 5, returned as a float such as 4.0, and it is a separate number that is often null for apartments and guest houses. Individual reviews from hotels/reviews are also scored out of 10, one score per guest.
Why does page_name not match the hotel's name?▾
Because it is a legacy URL slug rather than a name. Measured on 2026-08-27: page_name le-grand-gite-de-la-doye returns hotel_id 6929456, name "Residence du Louvre", address 1 Rue de Rohan, Paris. Booking keeps the original slug when a property is relisted or renamed, so a slug can describe something that no longer exists there. Join your records on hotel_id and use page_name only to address the page.
What are dest_id and dest_type, and why is dest_id negative?▾
They come from destinations/autocomplete and together they name a place to search. dest_type values seen live are city, district, landmark, airport, region and hotel. City ids are frequently negative (Paris -1456928, Istanbul -755070, Tokyo -246227, Rome -126693) while districts, landmarks and airports are small positive numbers (Taksim 1053, Eiffel Tower 735, Heathrow 4). The minus sign is part of the id, pass it through unchanged. Some newer entries break the pattern, New York came back as 20088325, so read the sign off the response rather than assuming it.
Why are latitude and longitude null on hotels?▾
The search and detail surfaces do not publish per-property coordinates, so location.latitude, location.longitude and coordinates.latitude/longitude all come back null. What you do get is location.address, location.city, location.country_code, a display string such as "18th arr., Paris" and a distance string such as "2.2 miles from downtown". destinations/autocomplete does return real coordinates for the destination itself, for example 48.85668 and 2.3514764 for Paris.
What is room_id and how does it relate to hotel_id?▾
room_id is the hotel_id with a room index appended, confirmed on two properties: hotel 237896 has rooms 23789607 and 23789612, hotel 7833434 has 783343401 and 783343402. That means you can read the parent property straight off a room id. Reviews carry the same value in their stay data, so a review can be tied to the exact room type the guest booked.
Why did hotels/detail come back mostly null for one hotel and complete for another?▾
Because detail is assembled from whatever the property page served, and meta says which case you got. For celine-taxim, meta reported completeness_pct 100.0 and room_detail_source "captured", and url, address, star_rating and review_score were all populated. For hotel_id 237896 the same call reported completeness_pct 87.5 and room_detail_source "constructed_replay", and url, address, star_rating and review_score came back null while room_types and facilities were fine. Check meta.completeness_pct before trusting a sparse record. The two actions can also disagree on the display name after a rebrand, so key on hotel_id.
What is the Booking.com API?▾
Booking.com API is a ReefAPI endpoint group for search hotels with prices, scores and availability. It returns live JSON through POST requests under /booking/v1.
Is the Booking.com API free to try?▾
Yes. ReefAPI starts with 1,000 free credits, no card required. Booking.com calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Booking.com login or account?▾
No login to Booking.com is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Booking.com data?▾
The page example is captured from a live hotels/search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Booking.com API use?▾
Booking.com actions currently cost 1-3 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Booking.com from an AI assistant or MCP client?▾
Yes. Connect ReefAPI once through MCP and your assistant can call booking actions with the same key, credit pool and JSON envelope used by normal REST requests.
8 Travel & Lodging APIs on the same key
One key, one credit pool, one response envelope. If you are pulling Booking.com, you are one call away from the rest of the category — no second contract, no second integration.
Need something this API does not do?
Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.
Try it on your own data before you pay anything
The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 184 APIs, and the same envelope everywhere.
Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.