Overview
The Hotels.nl API gives your application — or your AI agent — direct access to real-time hotel availability and pricing across 2.5 million properties worldwide. Every request is a simple POST with a JSON body. Every response is clean, structured JSON ready for any LLM to parse and act on.
Two ways to search: send a location in plain text (a city, address, landmark — anything) and the API handles geocoding automatically, or pass latitude & longitude directly if you already have coordinates. Either way you get hotels with the cheapest available rate, including pricing, cancellation policy, and room details. For full rate listings, use the hotel detail endpoint. When your user picks a rate, one more call starts the booking — the guest clicks a single button to pay.
How it works
Always start with search. The search endpoint (/api/search.php) is the only way to find hotels — by name, location, or coordinates. You cannot look up a hotel by name on the hotel detail endpoint. Here's the full flow:
- Search — Call
/api/search.phpwith a location (e.g. "Hilton Amsterdam") and dates. You get a list of matching hotels, each with anidand the cheapest rate including ahotelsnl_hash. - Details — Take the
idfrom the search results and call/api/hotel.phpto get full hotel info, photos, policies, and all available rooms & rates. Each rate has its ownhotelsnl_hash. - Book — Send the
hotelsnl_hashof the chosen rate to/api/booking.php. You get back a URL on hotels.nl where the guest finalizes the booking and pays — all details are pre-filled, one click to confirm.
The hotel detail endpoint requires a numeric id that you can only obtain from a search. Even if a user asks about a specific hotel by name, search for it first — the API will find it.
Base URL
Quick Start
Three steps to your first hotel search:
# 1. Register and get your API key (20 seconds) # 2. Search hotels with one request: curl -X POST https://hotels.nl/api/search.php \ -H "Content-Type: application/json" \ -d '{ "apikey": "YOUR_API_KEY", "location": "Dam Square, Amsterdam", "checkin": "2026-06-15", "checkout": "2026-06-18" }' # 3. That's it. You get hotels with the cheapest rate and pricing back instantly.
Using an AI Agent?
If you're connecting an AI assistant or LLM agent to this API, point it to the Agent Instructions page. It's a plain-text document that contains everything an AI needs to understand the API, construct requests, and interpret responses — no HTML, no fluff. Just give your agent the API key and that URL.
Authentication
Every request must include your API key in the JSON body as the apikey field. No headers, no OAuth, no tokens to refresh. One key, every request.
Don't have a key yet? Register here — it takes 20 seconds.
{
"apikey": "your_api_key_here",
...
}
Error Handling
The API uses standard HTTP status codes. Errors return a JSON object with an error field.
- 200 Success
- 400 Bad Request — missing or invalid parameters
- 401 Unauthorized — API key is missing
- 403 Forbidden — API key is invalid
- 405 Method Not Allowed — only POST accepted
- 429 Too Many Requests — rate limit exceeded
{
"error": "Required: location, checkin, checkout"
}
Rate Limits
To ensure fair usage and protect the underlying hotel suppliers, the search.php and hotel.php endpoints are rate-limited per IP address.
requests per minute
per endpoint, per IP
requests per day
per endpoint, per IP
When a limit is exceeded, the API returns HTTP 429 with a Retry-After header indicating how many seconds to wait. The response body contains an error field explaining which limit was reached.
{
"error": "Rate limit exceeded: maximum 5 requests per minute. Please wait and try again."
}
The default limits are sufficient for most use cases. If your application requires more requests, contact info@hotels.nl to request a higher daily quota. Include your API key and a description of your use case.
Endpoints
⚡ Rate-limited: 5 requests/minute, 200 requests/day per IP. See Rate Limits.
Input Parameters
| Name | Type | Description | |
|---|---|---|---|
| apikey | string | required | Your API key |
| checkin | string | required | Check-in date (YYYY-MM-DD) |
| checkout | string | required | Check-out date (YYYY-MM-DD) |
| Option A — Search by location text | |||
| location | string | City, address, landmark — anything. Automatically geocoded via Google. | |
| Option B — Search by coordinates | |||
| latitude | float | Latitude of search center (e.g. 52.3731) | |
| longitude | float | Longitude of search center (e.g. 4.8932) | |
Provide either | |||
| Optional filters | |||
| residency | string | Guest country code, e.g. nl. Default: nl | |
| language | string | Response language. Default: nl | |
| currency | string | Price currency (ISO 4217). Default: EUR | |
| radius | int | Search radius in meters (1–10000). Default: 5000 | |
| persons | int | Number of persons for the room (1–5). Default: 2 | |
| star_rating | int[] | Filter by stars: [3,4,5]. 0 = unrated. Default: [1,2,3,4,5] (excludes unrated) | |
| kind | string[] | Property type filter. Values: Hotel, Apartment, Apart-hotel, BNB, Boutique_and_Design, Camping, Castle, Cottages_and_Houses, Farm, Glamping, Guesthouse, Hostel, Mini-hotel, Resort, Sanatorium, Villas_and_Bungalows. Default: ["Hotel"] | |
| meal_type | string[] | Meal filter. Values: nomeal, breakfast. Only these two meal plans are available. | |
| price_from | int | Minimum total price | |
| price_to | int | Maximum total price | |
| Optional output toggles | |||
| include_description | bool | Include short_description per hotel. Default: false | |
| include_amenities | bool | Include amenities per hotel. Default: true | |
Search results return only the single lowest-priced rate per hotel and are limited to 15 hotels. Use a specific location (street, neighborhood, landmark) for the best results. To see all rooms and rates, call /api/hotel.php with the hotel id.
Response Fields
| Field | Description | ||
|---|---|---|---|
| search_id | Unique cache key for this search. Pass to hotel.php for instant rate retrieval. | ||
| search | Echo of search parameters used (see below). | ||
| total_hotels | Number of hotels in the response (max 15). | ||
| hotels | Array of hotel objects (see below). | ||
search object
| Field | Description | ||
|---|---|---|---|
| checkin | Check-in date used | ||
| checkout | Check-out date used | ||
| nights | Number of nights (calculated) | ||
| latitude | Latitude of search center (geocoded or as provided) | ||
| longitude | Longitude of search center | ||
| radius_m | Search radius in meters | ||
| currency | Currency used for prices | ||
| language | Language used for results | ||
| residency | Guest residency country code | ||
| persons | Number of persons (1–5) | ||
hotels[] — each hotel object
| Field | Description | ||
|---|---|---|---|
| id | Internal hotel ID. Use this for hotel.php calls. | ||
| name | Hotel name | ||
| address | Street address | ||
| city | City name | ||
| country_code | Two-letter country code (e.g. NL) | ||
| star_rating | Star rating (0–5, 0 = unrated) | ||
| kind | Property type (e.g. Hotel, Apartment) | ||
| latitude | Hotel latitude | ||
| longitude | Hotel longitude | ||
| image | Hotel photo URL | ||
| short_description | Hotel description text. Only when include_description: true | ||
| amenities | Comma-separated amenities string. Included by default. Set include_amenities: false to omit. | ||
| rate | The single cheapest rate for this hotel (see below). | ||
rate object
| Field | Description | ||
|---|---|---|---|
| hotelsnl_hash | Booking reference hash. Send this to /api/booking.php to start a reservation. Deterministic ID built from hotel_id, room type, rate type (1-4), dates, and persons. Format: {hotel_id}-{room_code}-{rate_type}-{YYYYMMDD}-{YYYYMMDD}-{persons}. Rate types: 1=non-refundable+nomeal, 2=non-refundable+breakfast, 3=refundable+nomeal, 4=refundable+breakfast. | ||
| search_hash | Internal search reference used by the booking process. Passed along automatically — no action required from the consumer. | ||
| room | Room details object (see below) | ||
| meal | Meal plan: nomeal or breakfast | ||
| pricing | Pricing details object (see below) | ||
| cancellation | Cancellation policy object (see below) | ||
rate.room object
Fields that are null or false are omitted from the response.
| Field | Description | ||
|---|---|---|---|
| room_name | Full room name (localized) | ||
| room_class | Room type: Room, Suite, Studio, Apartment, etc. | ||
| quality | Quality level: Standard, Comfort, Deluxe, Superior, Economy, etc. | ||
| bedding | Bed type: Double Bed, Twin, Single, Multiple Beds, etc. | ||
| bedrooms | Number of bedrooms (omitted when 0 or null) | ||
| capacity | Occupancy: Single, Double, Triple, Quadruple, etc. | ||
| bathroom | Bathroom type: Private, Shared | ||
| view | View type (e.g. Sea View, City View). Omitted when none. | ||
| balcony | true if room has a balcony. Omitted when false. | ||
| family_room | true if family room. Omitted when false. | ||
| club_room | true if club/executive room. Omitted when false. | ||
| floor | Floor type (e.g. Upper, Ground). Omitted when none. | ||
| amenities | Array of room-level amenity tags (e.g. ["non-smoking", "queen-bed"]) | ||
rate.pricing object
| Field | Description | ||
|---|---|---|---|
| total_price | Total price for the entire stay (string) | ||
| currency | Price currency code (e.g. EUR) | ||
| price_per_night | Array of per-night prices (strings), one entry per night | ||
| taxes | Array of tax objects. Only shown when not included in price and amount > 0. Each: {name, amount, currency} | ||
| vat | VAT object {amount, currency}. Only shown when not included in price and amount > 0. | ||
rate.cancellation object
| Field | Description | ||
|---|---|---|---|
| free_cancellation_before | ISO datetime before which cancellation is free. null if non-refundable. | ||
| policies | Array of penalty periods. Each: {starts_at, ends_at, penalty_amount, penalty_charge} | ||
Response Codes
- 200 Hotels found
- 400 Missing required fields
- 401 Missing API key
- 403 Invalid API key
Request — by location (all options)
{
"apikey": "YOUR_API_KEY",
"location": "Rotterdam",
"checkin": "2026-10-22",
"checkout": "2026-10-25",
"residency": "nl",
"language": "nl",
"currency": "EUR",
"radius": 5000,
"persons": 2,
"star_rating": [3, 4, 5],
"kind": ["Hotel"],
"meal_type": ["breakfast"],
"price_from": 100,
"price_to": 500,
"include_description": true,
"include_amenities": true
}
Request — by coordinates (minimal)
{
"apikey": "YOUR_API_KEY",
"latitude": 51.9244,
"longitude": 4.4777,
"checkin": "2026-10-22",
"checkout": "2026-10-25"
}
Response Example
{
"search_id": "5d662193a16efae1349d...",
"search": {
"checkin": "2026-10-22",
"checkout": "2026-10-25",
"nights": 3,
"latitude": 51.9244201,
"longitude": 4.4777326,
"radius_m": 5000,
"currency": "EUR",
"language": "nl",
"residency": "nl",
"persons": 2
},
"total_hotels": 20,
"hotels": [
{
"id": 603138,
"name": "Hotel Port",
"address": "Pieter De Hoochweg 115, Rotterdam",
"city": "Rotterdam",
"country_code": "NL",
"star_rating": 3,
"kind": "Hotel",
"latitude": 51.90728,
"longitude": 4.45917,
"image": "https://cdn.worldota.net/t/900x900/...",
"short_description": "Hotel Port is located in Rotterdam, minutes from the city center...",
"amenities": "24-hour reception,Elevator/lift,Free Wi-Fi,Restaurant,Parking,...",
"rate": {
"hotelsnl_hash": "1584-a0b2c3d0e2f3g0h0i0j2k0l0-1-20260615-20260618-2",
"search_hash": "sr-019d1f54-6ee0-7a9e-8cef-a87c39a6cb98",
"room": {
"room_name": "Standaard Vierpersoonskamer",
"room_class": "Room",
"quality": "Standard",
"bedding": "Multiple Beds",
"capacity": "Quadruple",
"bathroom": "Private",
"amenities": ["not-guaranteed", "non-smoking"]
},
"meal": "nomeal",
"pricing": {
"total_price": "499.00",
"currency": "EUR",
"price_per_night": ["166.33", "166.33", "166.33"],
"taxes": [
{
"name": "city_tax",
"amount": "35.22",
"currency": "EUR"
}
]
},
"cancellation": {
"free_cancellation_before": null,
"policies": [
{
"starts_at": null,
"ends_at": null,
"penalty_amount": "499.00",
"penalty_charge": "499.00"
}
]
}
}
},
// ... more hotels (max 15)
]
}
Returns full hotel details together with room availability and rates. You must provide either a search_id from a previous search or checkin + checkout dates. Requests without dates are not accepted.
⚡ Rate-limited: 5 requests/minute, 200 requests/day per IP. See Rate Limits.
This endpoint requires a numeric hotel id, which you can only get from a /api/search.php response. You cannot search by hotel name here. Always start with a search, then use the id from the results to call this endpoint.
Required Parameters
| Name | Type | Description | |
|---|---|---|---|
| apikey | string | required | Your API key |
| id | int | required | Hotel ID from the id field in search results |
Availability (one method required)
| Name | Type | Description | |
|---|---|---|---|
| Method 1 — Use a previous search | |||
| search_id | string | The search_id from a search response. Pulls this hotel's rates from the cached search. | |
| Method 2 — Fresh availability lookup | |||
| checkin | string | Check-in date (YYYY-MM-DD) | |
| checkout | string | Check-out date (YYYY-MM-DD) | |
| persons | int | Number of persons for the room (1–5). Default: 2 | |
| currency | string | Price currency. Default: EUR | |
| residency | string | Guest country code. Default: nl | |
One of these methods is required. | |||
Optional
| Name | Type | Description | |
|---|---|---|---|
| language | string | Response language. Default: en |
Response Fields (static)
| Field | Description | ||
|---|---|---|---|
| id | Internal hotel ID | ||
| name | Hotel name | ||
| location | Address, coordinates, city, country, distance to center | ||
| times | Check-in/out times, front desk hours | ||
| property | Total rooms, floors, year built/renovated, payment methods | ||
| descriptions | Structured text descriptions | ||
| images | Array of {url, category} — 1024×768 photos with category label | ||
| amenities | Grouped amenities (included + paid) | ||
| policies | Internet, parking, meals, pets, extra beds, shuttle | ||
Response Fields (when availability requested)
| Field | Description | ||
|---|---|---|---|
| availability | Source (search_cache or live), dates, nights, currency. Contains message if no rooms found. | ||
| rooms | Array of room objects, grouped by type (class + quality + bedding). Room fields that are null or false are omitted. Each room contains a rates array with up to 4 options: nomeal/breakfast × refundable/non-refundable. Only the cheapest per combination is shown. Each rate includes hotelsnl_hash (deterministic booking reference — send to /api/booking.php to reserve), search_hash (internal reference for booking process), meal, refundable, pricing, cancellation, and booking. Taxes/VAT are only shown if not included and amount > 0. Empty array if no rooms available. | ||
Response Codes
- 200 Hotel details returned
- 400 Missing hotel ID, or missing search_id / checkin+checkout
- 403 Invalid API key
- 404 Hotel not found in database
Request — With search_id (preferred)
{
"apikey": "YOUR_API_KEY",
"id": 1584,
"search_id": "a3f8c9..."
}
Request — Fresh availability
{
"apikey": "YOUR_API_KEY",
"id": 1584,
"checkin": "2026-06-15",
"checkout": "2026-06-18",
"persons": 2
}
Response — With availability
{
"id": 1584,
"name": "NH Groningen",
"type": "Hotel",
"star_rating": 4,
"location": {
"address": "Hanzeplein 132",
"city": "Groningen",
"country_code": "NL"
},
"times": {"check_in": "15:00", "check_out": "12:00"},
"property": {"total_rooms": 155, "floors": 7},
"descriptions": [...],
"images": [
{"url": "https://cdn.worldota.net/t/1024x768/...", "category": "Exterior"},
{"url": "https://cdn.worldota.net/t/1024x768/...", "category": "Guest Rooms"}
],
"amenities": [...],
"policies": {...},
"availability": {
"source": "search_cache",
"checkin": "2026-06-15",
"checkout": "2026-06-18",
"nights": 3,
"currency": "EUR"
},
"rooms": [
{
"room_name": "Standard Double",
"room_class": "Room",
"quality": "Standard",
"bedding": "Double",
"capacity": "Double",
"bathroom": "Private",
"rates": [
{
"hotelsnl_hash": "1584-a0b2c3d0e2f3g0h0i0j2k0l0-1-20260615-20260618-2",
"search_hash": "sr-019d1f54-6ee0-7a9e-8cef-a87c39a6cb98",
"meal": "nomeal",
"refundable": false,
"pricing": {
"total_price": "389.00",
"currency": "EUR",
"price_per_night": ["129.67", "129.67", "129.66"]
},
"cancellation": {
"free_cancellation_before": null,
"policies": [...]
},
"booking": {"rooms_available": 3}
},
{
"hotelsnl_hash": "1584-a0b2c3d0e2f3g0h0i0j2k0l0-4-20260615-20260618-2",
"search_hash": "sr-019d1f54-6ee0-7a9e-8cef-b92d48b7dc42",
"meal": "breakfast",
"refundable": true,
"pricing": {
"total_price": "429.00",
"currency": "EUR",
"price_per_night": ["143.00", "143.00", "143.00"],
"taxes": [{"name": "city_tax", "amount": "9.30", "currency": "EUR"}]
},
"cancellation": {
"free_cancellation_before": "2026-06-13T14:00:00",
"policies": [...]
},
"booking": {"rooms_available": 5}
}
]
}
]
}
Response — No availability
{
"id": 1584,
"name": "NH Groningen",
...
"availability": {
"source": "live",
"checkin": "2026-12-31",
"checkout": "2027-01-01",
"message": "No rooms available for the requested dates."
},
"rooms": []
}
Initiates a hotel reservation. Send the hotelsnl_hash from any rate in the search or hotel response together with your API key. The system takes it from there — you get back a URL where the guest finalizes the booking with a single click.
The hotel providers we work with have extremely complex booking systems that require many technical steps behind the scenes — availability checks, rate verification, pre-booking confirmations, payment tokenization, and more. None of this is relevant to your user. We handle all of it server-side so your integration stays simple. The finalization page the guest lands on already has all their details pre-filled (name, email, phone from registration). All they need to do is press one button to start the payment process and confirm the reservation.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| apikey | string | required | Your API key |
| hotelsnl_hash | string | required | The hotelsnl_hash from any rate in a search or hotel response. Contains the hotel, room type, meal plan, dates, and number of persons. |
That's it — just two fields. The hotelsnl_hash encodes all reservation details (hotel, room, rate type, dates, persons). Guest information is automatically pulled from your registered account.
What happens after the call
- A booking record is created with status processing.
- Our system starts working through the provider's multi-step booking pipeline in the background — verifying availability, locking the rate, confirming pricing, and preparing the payment session.
- The returned URL points to a finalization page on hotels.nl where the guest reviews the booking summary and completes payment with one click.
Response Fields
| Field | Description | ||
|---|---|---|---|
| status | "ok" when the booking was successfully initiated. | ||
| booking_url | URL to the finalization page. Redirect the guest here or present it as a link. The page has all guest data pre-filled — one button to pay and confirm. | ||
Response Codes
- 200 Booking initiated successfully
- 400 Missing or invalid hotelsnl_hash
- 401 Missing API key
- 403 Invalid API key
The finalization page is designed for speed. We pre-fill the guest's name, email, and phone number from their API account. The guest sees a clean summary of the hotel, room, dates, price, and cancellation policy — then clicks one button to pay. No forms to fill out, no re-entering details.
Request
{
"apikey": "YOUR_API_KEY",
"hotelsnl_hash": "1584-a0b2c3d0e2f3g0h0i0j2k0l0-1-20260615-20260618-2"
}
Response
{
"status": "ok",
"booking_url": "https://hotels.nl/api/book/finalize.php?id=hFHUbO5sDBTeu0lLT6ZuDz8yhysv"
}
What the guest sees
The finalization page at the booking_url shows:
- Hotel name, room type, and bedding
- Check-in / check-out dates and number of nights
- Total price, city tax (if any), and meal plan
- Cancellation policy with deadline
- Guest details (pre-filled from account)
- One button to confirm and pay
Returns a list of all bookings associated with your API key. Only bookings that have progressed past the initial creation stage are included (i.e. bookings where a payment was attempted). Results are sorted by booking date, newest first.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| apikey | string | required | Your API key |
Response Fields
| Field | Description | ||
|---|---|---|---|
| status | "ok" on success. | ||
| count | Total number of bookings returned. | ||
| bookings | Array of booking objects (see below). | ||
Booking Object
| Field | Description | ||
|---|---|---|---|
| booking_id | Hotels.nl internal booking ID. | ||
| bookhash | Unique booking reference hash. Use this to retrieve details or cancel. | ||
| booked_at | Date and time the booking was created. | ||
| arrival | Check-in date (YYYY-MM-DD). | ||
| departure | Check-out date (YYYY-MM-DD). | ||
| guest_name | Full name of the lead guest. | ||
| hotel_name | Name of the booked hotel. | ||
| room_name | Room type description. | ||
| status | One of: payment_failed, booking_failed, booking_confirmed, booking_cancelled. | ||
Response Codes
- 200 Success — bookings returned (may be empty array)
- 401 Missing API key
- 403 Invalid API key
Request
{
"apikey": "YOUR_API_KEY"
}
Response
{
"status": "ok",
"count": 2,
"bookings": [
{
"booking_id": 14,
"bookhash": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234",
"booked_at": "2026-03-25 14:32:01",
"arrival": "2026-06-15",
"departure": "2026-06-18",
"guest_name": "John Doe",
"hotel_name": "Grand Hotel Bonanno",
"room_name": "Superior Double Room",
"status": "booking_confirmed"
},
{
"booking_id": 12,
"bookhash": "xYzAbCdEfGhIjKlMnOpQrStUvWx9876",
"booked_at": "2026-03-20 09:15:44",
"arrival": "2026-07-01",
"departure": "2026-07-04",
"guest_name": "Jane Smith",
"hotel_name": "Hotel Bernini Palace",
"room_name": "Deluxe Twin Room",
"status": "booking_cancelled"
}
]
}
Retrieves all details for a single booking. The booking must belong to the account associated with the API key. Returns comprehensive information including hotel details, guest data, pricing, cancellation policy, and current status.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| apikey | string | required | Your API key |
| bookhash | string | required | The 30-character booking reference hash (from booking_overview or the original booking response). |
Key Response Fields
| Field | Description | ||
|---|---|---|---|
| status | "ok" on success. | ||
| booking | Object containing all booking fields (see example). | ||
| booking.status | One of: new, processing, booking_failed, booking_confirmed, booking_cancelled. | ||
| booking.refundable | true if the rate allows free cancellation, false for non-refundable rates. | ||
| booking.free_cancellation_before | Deadline for free cancellation (ISO datetime string), or null if non-refundable. | ||
| booking.hotel_name | Hotel name from our database. | ||
| booking.hotel_address | Hotel street address. | ||
The response includes all booking fields except internal system fields (hashes, internal IDs, Mollie payment details). Hotel information (name, address, city, country, stars, phone, image) is joined automatically.
Response Codes
- 200 Success — booking details returned
- 400 Missing bookhash
- 401 Missing API key
- 403 Invalid API key or booking belongs to another account
- 404 Booking not found
Request
{
"apikey": "YOUR_API_KEY",
"bookhash": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234"
}
Response
{
"status": "ok",
"booking": {
"id": 14,
"user_id": 1,
"hotel_id": 1584,
"arrival": "2026-06-15",
"departure": "2026-06-18",
"persons": 2,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "+31612345678",
"client_remarks": "Late arrival around 22:00",
"bookhash": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234",
"room_name": "Superior Double Room",
"bedding": "Double Bed",
"meal": "breakfast",
"total_price": "342.50",
"currency": "EUR",
"refundable": true,
"free_cancellation_before": "2026-06-02T21:59:00",
"status": "booking_confirmed",
"status_description": "booking_confirmed",
"paid": "yes",
"ratehawk_order_id": "H-12345678",
"hotel_name": "Grand Hotel Bonanno",
"hotel_address": "Via Carlo Francesco Gabba, 17",
"hotel_city": "Pisa",
"hotel_country": "IT",
"hotel_stars": 4,
"created_at": "2026-03-25 14:32:01"
}
}
Cancels a confirmed reservation. Only bookings with status booking_confirmed can be cancelled, and only within the free cancellation window. After the cancellation deadline, cancellation is no longer possible and no refund will be given.
Cancellation is only possible for refundable rates and only before the free_cancellation_before deadline. Non-refundable bookings cannot be cancelled. After the free cancellation deadline has passed, cancellation is no longer possible and no refund will be given. Use retrieve_booking.php to check whether a booking can still be cancelled.
Parameters
| Name | Type | Description | |
|---|---|---|---|
| apikey | string | required | Your API key |
| bookhash | string | required | The 30-character booking reference hash. |
Response Fields
| Field | Description | ||
|---|---|---|---|
| status | "cancelled" on success. | ||
| booking_id | Hotels.nl internal booking ID. | ||
| bookhash | The booking reference hash (echo). | ||
What happens after cancellation
- The cancellation is sent to the hotel supplier immediately.
- The booking status changes to
booking_cancelled. - A cancellation confirmation email is sent to the guest.
- Payment settlement is handled by our team within two working days.
Response Codes
- 200 Booking cancelled successfully
- 400 Missing bookhash
- 401 Missing API key
- 403 Invalid API key, or cancellation deadline passed / non-refundable
- 404 Booking not found
Request
{
"apikey": "YOUR_API_KEY",
"bookhash": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234"
}
Success Response
{
"status": "cancelled",
"booking_id": 14,
"bookhash": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234"
}
Error: Deadline Passed
{
"error": "Free cancellation deadline (2026-06-02T21:59:00) has passed. Contact info@hotels.nl for assistance."
}
Error: Already Cancelled
{
"error": "This reservation has already been cancelled.",
"status": "already_cancelled"
}
For AI Agent Developers
This API is specifically designed to be called by AI agents and LLM tool-use frameworks. Here's why it works out of the box:
No need to pre-geocode. Send "Central Park, NYC" or "Schiphol Airport" — we handle the rest.
No OAuth flows, no token refresh. Just pass apikey in the body. Perfect for agent tool definitions.
Clean JSON with predictable field names. No HTML, no XML, no pagination tokens to manage.
Identical searches within 1 hour return instantly from cache. Your agent can retry without wasting time or money.