Bookings and Reservations
Booking Experts only supports creating reservations for a single accommodation. Support for ordering multiple accommodations is under active development. This will be accomplished by supporting Bookings. Bookings will be able to contain multiple Reservations, as illustrated in the diagram below.
The current API leverages this redesigned structure by already supporting creation of bookings with a single reservation via POST reservation. When creation of bookings with multiple reservations is added, this will become possible via the endpoint POST booking.
Sideposting
As can be seen in the diagram, a Reservation belongs to a Booking and and Booking belongs to a Customer.
As the JSON:API specification does not yet support submission of multiple resources at once, we have introduced the concept of Sideposting. Sideposting will allow you to post new related resources using the standard included array. These resources don't have an ID yet, therefore it is required to link these resources by setting /meta/temp_id
. You will also need to define what the system needs to do with these resources by specifying /meta/method
(= create or update) on the relationship.
Creating a reservation
For a reservation to be accepted, you need to (at least) specify the following attributes:
start_date
end_date
rentable_type
guest_group
A valid example can be seen below - Endpoint : POST reservation.
{
"data": {
"type": "reservation",
"attributes": {
"start_date": "2014-01-08",
"end_date": "2014-01-15",
"guest_group": {
"seniors": 0,
"adults": 2,
"adolescents": 0,
"children": 0,
"babies": 0,
"pets": 0
}
},
"relationships": {
"rentable_type": {
"data": {
"id": "123",
"type": "rentable_type"
}
}
}
}
}
Creating an option
In Booking Experts, an option is a reservation that expires after a configured amount of days when it is not accepted by the customer. To create an option, you can use the same endpoint and pass the option_validity
attribute, which defines the option validity in days.
line 8 ⬇️
Notice the difference with the code above
//Endpoint: POST reservation
{
"data": {
"type": "reservation",
"attributes": {
"start_date": "2014-01-08",
"end_date": "2014-01-15",
"option_validity": 5,
"guest_group": {
"seniors": 0,
"adults": 2,
"adolescents": 0,
"children": 0,
"babies": 0,
"pets": 0
}
},
"relationships": {
"rentable_type": {
"data": {
"id": "123",
"type": "rentable_type"
}
}
}
}
}
Creating a reservation with customer and booking details
It's essential to add Customer details. Booking attributes are relevant as well, like redeemable codes
or an after payment return url
. In this case, you will need to use Sideposting to include these details when creating a new reservation.
The example below is a more complex example that shows how this can be done.
This example does not only specify booking and customer details, but also includes some ordered extras (ExtraOrderItem) and a couple of custom cancellation rules (CancellationRule). Resource linking has been realized by properly setting temp_id
. As these resources are new, the method passed in each relationship is create
.
{
"data": {
"type": "reservation",
"attributes": {
"start_date": "2014-01-08",
"end_date": "2014-01-15",
"late_checkout": false,
"locale": "en",
"note": "Please note",
"currency": "EUR",
"price_according_to_channel": { "currency": "EUR", "value": "85.75" },
"guest_group": {
"seniors": 0,
"adults": 1,
"adolescents": 0,
"children": 1,
"babies": 0,
"pets": 0
},
"license_plates": ["19XNZ1"]
},
"relationships": {
"rentable_type": {
"data": {
"id": "123",
"type": "rentable_type"
}
},
"booking": {
"data": {
"type": "booking",
"meta": {
"temp_id": "booking-id",
"method": "create"
}
}
},
"primary_package": {
"data": {
"id": "1",
"type": "primary_package"
}
},
"extra_packages" : {
"data": [{
"id": "101",
"type": "extra_package"
}]
},
"extra_order_items": {
"data": [{
"type": "extra_order_item",
"meta": {
"temp_id": "extra-id",
"method": "create"
}
}]
},
"cancellation_rules": {
"data": [{
"type": "cancellation_rule",
"meta": {
"temp_id": "cancellation-rule-1",
"method": "create"
}
},{
"type": "cancellation_rule",
"meta": {
"temp_id": "cancellation-rule-2",
"method": "create"
}
}]
},
"reservation_amenities": {
"data": [{
"type": "reservation_amenity",
"meta": {
"temp_id": "reservation-amenity-1",
"method": "create"
}
}]
}
}
},
"included": [{
"type": "booking",
"attributes": {
"remote_booking_nr": "12345",
"after_payment_return_url": "https://www.example.com/callback",
"redeemable_codes": ["DISCOUNT2021"]
},
"relationships": {
"customer": {
"data": {
"type": "customer",
"meta": {
"temp_id": "customer-id",
"method": "create"
}
}
}
},
"meta": {
"temp_id": "booking-id"
}
},{
"type": "customer",
"attributes": {
"title": "family",
"first_name": "RIV",
"last_name": "Rowe",
"email": "[email protected]",
"phone": "+31612345678",
"is_company": false,
"date_of_birth": "1955-05-05",
"receive_newsletter": false,
"address": "78229 Marquerite Flat",
"number": null,
"postalcode": "03756",
"city": "Amsterdam",
"country_code": "NL",
"has_custom_invoice_details": true,
"custom_invoice_details": {
"name": "Ali",
"email": "[email protected]",
"address": "Het Eeftink 11-12",
"postalcode": "7541 WH",
"city": "Enschede",
"country_code": "NL"
}
},
"meta": {
"temp_id": "customer-id"
}
},{
"type": "extra_order_item",
"attributes": {
"quantity": 2,
"guest_answer": "Guest answer"
},
"relationships": {
"extra": {
"data": {
"id": "245",
"type": "extra"
}
}
},
"meta": {
"temp_id": "extra-id"
}
},{
"type": "cancellation_rule",
"attributes": {
"percentage": 33.3,
"days_before_arrival": 28,
"administration_costs": { "currency": "EUR", "value": "0.00" }
},
"meta": {
"temp_id": "cancellation-rule-1"
}
},{
"type": "cancellation_rule",
"attributes": {
"percentage": 100,
"days_before_arrival": 14,
"administration_costs": { "currency": "EUR", "value": "10.00" }
},
"meta": {
"temp_id": "cancellation-rule-2"
}
},{
"type": "reservation_amenity",
"relationships": {
"amenity": {
"data": {
"id": "1",
"type": "amenity"
}
}
},
"meta": {
"temp_id": "reservation-amenity-1"
}
}]
}
Updating a reservation
A reservation, it's booking, and customer details can be updated in the same way as creating reservations.
For existing resources you are now required to pass their actual ID in stead of their temp_id
. If you like to update a related resource, you need to explicitly specify this by setting /meta/method
to update on the relationship.
As an example, consider the code below : it shows an example of how to update the redeemable codes array of the booking of a reservation.
{
"data": {
"id": "3245",
"type": "reservation",
"attributes": {
"start_date": "2014-01-08",
"end_date": "2014-01-15",
"currency": "EUR",
"guest_group": {
"seniors": 0,
"adults": 2,
"adolescents": 0,
"children": 0,
"babies": 0,
"pets": 0
}
},
"relationships": {
"rentable_type": {
"data": {
"id": "123",
"type": "rentable_type"
}
},
"booking": {
"data": {
"id": "3245",
"type": "booking",
"meta": {
"method": "update"
}
}
}
}
},
"included": [{
"id": "3245",
"type": "booking",
"attributes": {
"redeemable_codes": ["DISCOUNT2021", "FREEFORALL"]
}
}]
}
Cancelling a reservation
A reservation can be cancelled by sending an existing reservation resource. Optionally, you can pass the cancel_date
and cancel_reason
attributes to set a custom date and reason for cancelling.
{
"data": {
"id": "3245",
"type": "reservation",
"attributes": {
"cancel_date": "2014-01-05",
"cancel_reason": "COVID",
}
}
}
Payment of reservations
To initiate a payment of a Reservation, look at the Booking of the Reservation.
When this Booking can be paid, it will have a pay_url
link to which the user should be redirected.
After payment, the user will be redirected back to the after_payment_return_url
that was set when the Booking was created.
A query parameter status will be passed that can have the following values:
success
: The amount has been paid. You can show a 'Thank you' page. The guest has received a confirmation of the Reservation via email.open_but_confirmed
: The amount has not been paid yet, but the Reservation has been confirmed. This can happen when a bank transfer is initiated. It should be handled as a success.failure
: The payment has been failed, but there is a possibility that the status may still change. In the booking process, this should be handled in the same way as failure_final.failure_final
: The payment has failed and this will not change anymore (end state). You can ask the user to initiate a new payment by rendering a payment link to the pay_url again.cancelled
: The payment has been cancelled. You can ask the user to initiate a new payment by rendering a payment link to the pay_url again.
Error codes
When mutating reservations fail, error messages usually contain a detailed error code in meta.error
, which you can use to generate a custom error message.
allotment_full
: Accommodation is already occupied or not rentable for the given period since it is needed for an allotmentblocked
: Accommodation is blockedcannot_be_in_the_past
: Start date cannot be in the pastcurrent_allotment_full
: Accommodation is full for the current channelinvalid_guest_group
: The specified guest group is invalidmaximum_stay
: Reservation exceeds maximum stayminimum_stay
: Reservation does not meet minimum staymust_contain_at_least_one_adult_or_senior
: At least one senior or adult must be part of the guest groupno_accommodation_found_for_amenities
: No accommodation found for the passed amenitiesno_accommodation_found_for_pets
: No accommodation found in which pets are allowedno_arrival
: The given start date is not a valid arrival dateno_available_accommodation_found
: All accommodations are occupied in the given periodno_checkout
: The given start date is not a departure dateno_prices
: There are no prices in the given period for the chosen accommodationoccupied
: The accommodation is already occupied in the given periodpast_or_already_closed_reception
: The arrival date is in the past or the reception has already been closed for today
Updated about 1 month ago