Quote and book a stay
Get a firm price, show it with its terms, and confirm the booking.
To book a stay, quote it, show the guest the quote, and send the reservation within 15 minutes.
Quote the stay
Call Create a quote when the guest opens checkout, not on every page view. A quote asks the PMS for its current price, which is slower and costlier than search.
For a MULTI_UNIT or COMPLEX listing, send the unitID the guest picked. To let OnSeason pick a free unit of a type, send roomType instead. If you send neither, OnSeason picks a free unit where the PMS supports it.
A 400 means the stay can't be sold as asked. Common causes are dates that are no longer free, a party that is too large, or a check-in date too close to today for the property. Show the guest other dates or other properties.
Show the guest what they pay
Show these parts of the quote before the guest confirms:
totalPriceandcurrency. This is the amount the booking is made at.- The breakdown in
components: nightly rates, fees, taxes, and discounts. Treat names and types you don't recognize as valid price lines. payAtProperty, when present. These are mandatory costs that the guest pays the property on site, such as a local tax or a deposit taken at key handover. They are not intotalPriceand are not charged at booking. Each one has its owncurrency, which can differ from the quote's, and aunitthat says what the price is per (stay,day,week,person,person_day,usage, orother).deposit, when it is above zero.- The cancellation terms in
cancellationPolicy.descriptionis a ready-made summary, or you can renderpenaltiesyourself. See Cancellation policies.
Book within 15 minutes
Call Create a reservation with the quoteToken before quoteTokenExpiresAt. Copy these values from the quote:
| Reservation field | Quote field |
|---|---|
quoteToken | quoteToken |
listingID | listingID |
checkInDate | checkInDate |
checkOutDate | checkOutDate |
guests | guests |
currency | currency |
totalBasePrice | components.basePrice.amount |
totalFeePrice | components.fees.amount, or 0 when absent |
totalTaxPrice | components.taxes.amount, or 0 when absent |
totalPrice | totalPrice |
unitID | The unitID you quoted, when you sent one |
listingID, the dates, guests, and unitID (when you send it) must match the quote, or the reservation is rejected. OnSeason books the prices, the provider metadata, and the cancellation terms that are signed into the token. The price fields in the body are still required.
Send the whole token as you received it. Don't decode it or depend on what is inside it.
Handle the response
A 201 with status CONFIRMED is the booking confirmation. Store:
id, the OnSeason reservation ID. You use it to read and cancel the booking.providerReservationID, the booking reference in the PMS.cancellationPolicy, the terms the guest booked under.- Your own booking reference, mapped to both IDs above.
The API has no field for your own booking reference, and source is not unique, so keep the mapping on your side.
If the reservation fails with 400, read the message:
Invalid or expired quoteToken: the token is past its 15 minutes or was changed. Quote again.Reservation does not match the signed quote: a bound field differs from the quote. Fix the request or quote again.Some dates are not available…orThis unit is no longer available…: someone else booked the dates after your quote. Show the guest other options.
If the request times out or the connection drops, don't send it again. Follow Handle timeouts and retries.