Skip to main content

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

ParameterTypeDescription
optionRefIdstringOption reference ID from search (must be quoted)
holderobjectBooking holder (main guest) information
roomsarrayRoom configurations with guest details

Optional Parameters

ParameterTypeDescription
paymentCardobjectPayment card information (if required)
clientReferencestringYour internal booking reference
remarksarrayBooking remarks
settingsobjectRequest 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

StatusDescription
CONFIRMEDBooking confirmed by supplier
PENDINGBooking request submitted, awaiting confirmation
ON_REQUESTSupplier needs to manually confirm
FAILEDBooking could not be completed

Booking References

Store these references for later operations:

  • bookingID - Bundleport booking ID (use for retrieve, cancel)
  • clientReference - Your internal reference
  • providerReference - Supplier confirmation number
  • confirmationNumber - 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 -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 }
]
}
]
}'

Next Steps