Create a Booking
The book endpoint creates a hotel reservation. Always quote the option immediately before booking to ensure accurate pricing and availability.
Endpoint
POST /hotels/v1/bookings
Request
Required Parameters
| Parameter | Type | Description |
|---|---|---|
optionRefId | string | Option reference ID from search (must be quoted) |
holder | object | Booking holder (main guest) information |
rooms | array | Room configurations with guest details |
Optional Parameters
| Parameter | Type | Description |
|---|---|---|
paymentCard | object | Payment card information (if required) |
clientReference | string | Your internal booking reference |
remarks | array | Booking remarks |
settings | object | Request settings |
Example Request
{
"optionRefId": "OPT-123456789",
"holder": {
"name": "John",
"surname": "Doe",
"email": "john.doe@example.com",
"phone": "+34600123456",
"nationality": "ES"
},
"rooms": [
{
"occupancyRefId": 1,
"paxes": [
{
"name": "John",
"surname": "Doe",
"age": 35,
"type": "ADULT"
},
{
"name": "Jane",
"surname": "Doe",
"age": 33,
"type": "ADULT"
}
]
}
],
"paymentCard": {
"type": "VI",
"number": "4111111111111111",
"expire": {
"month": 12,
"year": 2027
},
"holder": {
"name": "John",
"surname": "Doe"
}
},
"clientReference": "BOOKING-2025-001",
"remarks": ["Late check-in requested"],
"settings": {
"accessIds": ["ACCESS_1"],
"requestId": "book-001"
}
}
Response
Success Response
{
"booking": {
"id": "BK-987654321",
"status": "CONFIRMED",
"reference": {
"bookingID": "BK-987654321",
"clientReference": "BOOKING-2025-001",
"providerReference": "SUPPLIER-12345",
"confirmationNumber": "HTL-67890"
},
"hotel": {
"code": "12345",
"name": "Example Hotel Barcelona"
},
"stay": {
"checkIn": "2025-06-15",
"checkOut": "2025-06-17"
},
"rooms": [
{
"description": "Standard Double Room",
"boardCode": "BB",
"confirmationReference": "ROOM-001",
"paxes": [
{
"name": "John",
"surname": "Doe",
"age": 35
},
{
"name": "Jane",
"surname": "Doe",
"age": 33
}
]
}
],
"holder": {
"name": "John",
"surname": "Doe",
"email": "john.doe@example.com",
"phone": "+34600123456"
},
"price": {
"currency": "EUR",
"net": 150.00,
"suggested": 180.00
},
"cancelPolicy": {
"refundable": true,
"cancelPenalties": []
},
"remarks": ["Late check-in requested"],
"createdAt": "2025-06-01T10:30:00Z",
"updatedAt": "2025-06-01T10:30:00Z"
},
"warnings": [],
"errors": []
}
On Request Response
Some bookings require supplier confirmation:
{
"booking": {
"id": "BK-987654321",
"status": "ON_REQUEST",
"reference": {
"bookingID": "BK-987654321"
},
...
},
"warnings": [
{
"code": "ON_REQUEST",
"description": "Booking requires supplier confirmation"
}
]
}
Key Fields
Booking Status
| Status | Description |
|---|---|
CONFIRMED | Booking confirmed by supplier |
PENDING | Booking request submitted, awaiting confirmation |
ON_REQUEST | Supplier needs to manually confirm |
FAILED | Booking could not be completed |
Booking References
Store these references for later operations:
bookingID- Bundleport booking ID (use for retrieve, cancel)clientReference- Your internal referenceproviderReference- Supplier confirmation numberconfirmationNumber- Hotel confirmation number
Holder Information
The holder is the main guest and booking contact:
- Required: name, surname, email
- Optional: phone, nationality
- Used for: booking confirmation, hotel communication
Guest Information (Paxes)
For each room, provide guest details:
- Adults: name, surname, age (optional)
- Children: name, surname, age (required)
- Type: "ADULT" or "CHILD"
Payment Card
Required for some suppliers. Include:
- Type: Card type (VI, MC, AX, etc.)
- Number: Card number
- Expire: Expiration month and year
- Holder: Cardholder name
Best Practices
1. Always Quote Before Booking
// ✅ Good - Quote then book
const quote = await quoteOption(optionRefId);
if (quote.errors?.length > 0) {
throw new Error('Option no longer available');
}
const booking = await bookOption(optionRefId, travellerData);
// ❌ Bad - Book without quoting
const booking = await bookOption(optionRefId, travellerData);
// May fail if price changed or option expired
2. Store All References
const booking = await bookOption(optionRefId, travellerData);
// Store all references
await saveBooking({
bundleportId: booking.booking.id,
clientReference: booking.booking.reference.clientReference,
providerReference: booking.booking.reference.providerReference,
confirmationNumber: booking.booking.reference.confirmationNumber,
status: booking.booking.status,
});
3. Handle On Request Bookings
const booking = await bookOption(optionRefId, travellerData);
if (booking.booking.status === 'ON_REQUEST') {
// Inform user that confirmation is pending
await notifyUser({
message: 'Your booking is being confirmed. You will receive an email when confirmed.',
bookingId: booking.booking.id,
});
// Set up webhook or polling to check status
await monitorBookingStatus(booking.booking.id);
}
4. Validate Guest Information
function validateGuests(rooms, occupancies) {
for (let i = 0; i < rooms.length; i++) {
const room = rooms[i];
const occupancy = occupancies[i];
// Check total guests match
const totalGuests = room.paxes.length;
const expectedTotal = occupancy.adults + (occupancy.children || 0);
if (totalGuests !== expectedTotal) {
throw new Error(`Room ${i + 1}: Expected ${expectedTotal} guests, got ${totalGuests}`);
}
// Check children ages
const children = room.paxes.filter(p => p.type === 'CHILD' || p.age < 18);
if (children.length !== (occupancy.children || 0)) {
throw new Error(`Room ${i + 1}: Children count mismatch`);
}
}
}
Code Examples
- cURL
- JavaScript
- Python
curl -X POST https://api.bundleport.com/hotels/v1/bookings \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"optionRefId": "OPT-123456789",
"holder": {
"name": "John",
"surname": "Doe",
"email": "john.doe@example.com"
},
"rooms": [
{
"occupancyRefId": 1,
"paxes": [
{ "name": "John", "surname": "Doe", "age": 35 },
{ "name": "Jane", "surname": "Doe", "age": 33 }
]
}
]
}'
async function createBooking(optionRefId, travellerData) {
// Quote first
const quote = await quoteOption(optionRefId);
// Book
const response = await fetch('https://api.bundleport.com/hotels/v1/bookings', {
method: 'POST',
headers: {
'Authorization': 'ApiKey YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
optionRefId,
holder: travellerData.holder,
rooms: travellerData.rooms,
paymentCard: travellerData.paymentCard,
clientReference: generateClientReference(),
}),
});
const booking = await response.json();
if (booking.errors?.length > 0) {
throw new Error(booking.errors[0].message);
}
return booking.booking;
}
import requests
def create_booking(option_ref_id, traveller_data):
# Quote first
quote = quote_option(option_ref_id)
# Book
url = "https://api.bundleport.com/hotels/v1/bookings"
headers = {
"Authorization": "ApiKey YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"optionRefId": option_ref_id,
"holder": traveller_data["holder"],
"rooms": traveller_data["rooms"],
"paymentCard": traveller_data.get("paymentCard"),
"clientReference": generate_client_reference(),
}
response = requests.post(url, json=payload, headers=headers)
booking = response.json()
if booking.get("errors"):
raise Exception(booking["errors"][0]["message"])
return booking["booking"]
Next Steps
- Retrieve Booking - Get booking details
- List Bookings - Query bookings
- Cancel Booking - Cancel a reservation