Scenario playbooks
Step-by-step handling for the situations every hotel integration meets, from a standard booking to on-request bookings, Book timeouts, cancellations, back-office sync and a sudden wave of 401 errors.
Each playbook says when to use it, then lists the steps in order. The booking flow explains the five calls they build on, and Pitfalls explains why the steps are there.
Standard booking
When: a guest books one room for two adults.
Quote with bestCombinations: true in filter and one distribution with two adults.
The guest picks a combination.
Confirm it. Show the authoritative price and cancellation policy, and collect the guest data listed in requiredField.
Prebook with the guest details. Compare the price, meal plan and cancellation policy with Confirm.
Book once and branch on status. See Booking statuses.
Store bookingReference, accommodation.bookingReference, your externalReference and auditData.traceId. Then send the voucher.
Family with two rooms
When: a party needs two rooms and one of them includes a child.
Quote with one distribution per room, and each guest's age at checkout.
{
"distributions": [
{ "persons": [{ "age": 35 }, { "age": 33 }] },
{ "persons": [{ "age": 40 }, { "age": 7 }] }
]
}Every combination's rooms[] now lists two rooms, one per distribution.
Prebook repeats the same two rooms in the same order. The child's requestedAge is their age at checkout and must equal the quoted age, 7.
The first person of room 2 is its room holder and gets the roomHolders fields from Confirm's requiredField.
Book and branch on status as in the standard booking.
More on occupancy and passenger fields in Rooms and guests.
Hotel page with every room
When: a Quote result had quoteSingleNeeded: true, or the guest lands on a hotel page directly. The combinations Quote already returned stay bookable.
Call Quote single with the hotel code, the dates and the rooms.
Group the combinations for your UI by rooms[].groupingRoomType, mealPlan.type and currentCancellationType.type.
Continue with Confirm, using the key of the combination the guest picks.
Price or policy changed
When: Confirm or Prebook returns PRICE_CHANGE or CANCELLATION_POLICIES_CHANGE in warnings[].
Show the old and the new price side by side.
For CANCELLATION_POLICIES_CHANGE, show the new cancellation policy. A refundable rate may have become non-refundable.
Continue to the next call only after the guest explicitly accepts. Otherwise stop the flow.
Checkout idle too long
When: the key (40 or 60 minutes) or the token (120 minutes) has expired, and the next step returns an error.
Get a new token. A new token means a new flow.
Quote single the same hotel with the same dates and rooms.
Select the same room, board and refundability as before.
If the price differs, follow Price or policy changed.
Continue with Confirm, Prebook and Book.
To make this rarer, show the guest a countdown during checkout.
On request (RQ)
When: Book returns RQ. This can happen even when onRequest was false throughout the flow.
Tell the guest the booking is pending hotel confirmation. Don't show it as confirmed.
Poll booking detail every 5 to 15 minutes, wait for a MODIFIED or CANCELED webhook, or both.
On BOOKED, confirm the booking to the guest.
On CANCELED or NOT_BOOKED, tell the guest, and refund them if you charged.
Set a deadline, for example 24 to 48 hours. After it, your operations team contacts your Nava account manager or the supplier.
Book timed out
When: Book returns no response, or the connection drops before you read it. The outcome is unknown, and a retry can book the room twice.
Don't call Book again, and don't charge the guest a second time.
Wait a minute. Your externalReference is already saved, because you save it before calling Book.
List today's bookings with List bookings.
Read each candidate with Get booking and compare its agencyBookingReference with your externalReference, then the hotel code and dates in hotelservice[].
Only if nothing matches, and both the key (60 minutes) and the token are still valid, call Book again with the same key. Otherwise start again from Quote and tell the guest.
This sequence is a recommendation, not a documented procedure.
Guest cancels
When: the guest asks to cancel a confirmed booking.
Call Cancellation fee. It quotes the penalty for cancelling today and changes nothing.
Show the guest what cancelling now costs and get their consent.
Call Cancel. Don't retry it automatically: after a timeout, read booking detail first.
Check that the response shows status: CANCELED.
Refund the guest, minus the fee: with Refund if the platform holds the payment, or through your own payment provider.
If you used Refund, a REFUND webhook arrives when it succeeds.
Refund moves money only. It does not cancel anything. More in Cancellations.
Supplier or agent cancels
When: a CANCELED or MODIFIED webhook arrives for a booking your guest didn't cancel.
Fetch the booking with Get booking. The webhook is only a signal.
Check the service status in hotelservice[]. CANCELED confirms the cancellation.
Tell the guest.
Reverse the booking in your accounting.
Back-office sync
When: you mirror bookings into your ERP, accounting or CRM system.
Receive the webhook, answer with a 2xx quickly and put the event on a queue.
A worker fetches the booking with Get booking.
Normalise hotelservice[], plus any other service arrays you need.
Upsert idempotently, keyed by booking, service bookingReference and passenger id.
Every hour, sweep the reference sequence with Get booking to catch lost webhooks and microsites that have no webhook.
Field-by-field guidance is in Reading bookings.
Hotel catalogue and SEO pages
When: you build hotel pages, maps or search from static content.
Once a week, page through the accommodation list.
Compare each hotel's lastUpdate with the value you stored. Only new and changed hotels need a new datasheet.
Fetch datasheets in batches of 100, once for each language you serve.
Store the images and facilities.
Never show prices from the catalogue. Prices only come from Quote.
The full sync design is in Hotel catalogue.
Agent edits a booking
When: a MODIFIED webhook arrives because an agent changed the booking in the back office.
Re-fetch the booking with Get booking.
Compare it with a hash of the version you stored last. Leave volatile fields such as historical[] and auditData out of the hash.
Record what changed: dates, room, price or passengers.
Read historical[] for a human-readable account of what happened.
Every call returns 401
When: a working integration suddenly gets 401 on every call. A wrong password and a deleted API user return the same 401.
Stop retry storms and alert your team.
Ask your Nava account manager whether the API user still exists. It may have been deleted, or its credentials rotated.
Update the credential in every deployed service.
Replay the failed sync jobs from your event store. A booking flow that failed restarts from Quote with a new token.
Expect a brief second wave of failures: after you change environment variables on a hosting platform, old instances can still run a few jobs with the old credential. Replay those too.
Related
Pitfalls
Where the spec and the docs disagree, and the mistakes that break hotel integrations most often, from the booking flow to reading bookings in production. Each one comes with what to do instead.
FAQ
Short answers to the questions agencies ask most about search, rooms and guests, booking, hotel content and commercial terms, plus the passenger validation errors the API returns and how to prevent them.