Hotel guides
Collecting traveller details
The traveller list on a booking has to mirror the search exactly — the same rooms, adults and children's ages — and name real people. Here's how to build it.
One traveller per guest you searched for
Send a travelers entry for every adult and child in the search, grouped into rooms with roomIndex. Room numbers count from 0 in the order of your occupancy array.
"occupancy": [
{ "adults": 2, "childrenAges": [] },
{ "adults": 1, "childrenAges": [4, 9] }
]"travelers": [
{ "title": "Ms", "firstName": "Anna", "lastName": "Smith", "email": "anna.smith@example.com", "phone": "+447700900123", "nationality": "GB", "roomIndex": 0 },
{ "title": "Mr", "firstName": "Ben", "lastName": "Smith", "roomIndex": 0 },
{ "title": "Mrs", "firstName": "Priya", "lastName": "Shah", "roomIndex": 1 },
{ "title": "Master", "firstName": "Dev", "lastName": "Shah", "type": "child", "age": 4, "roomIndex": 1 },
{ "title": "Miss", "firstName": "Mira", "lastName": "Shah", "type": "child", "age": 9, "roomIndex": 1 }
]- The first traveller is the lead guest. Rooms are held in their name. Roave emails the confirmation to the booking's agent — for bookings made with an API key, the admin who created the key — not to the traveller. Send travellers their voucher yourself, or with email-client.
- Children need
type: "child"and the sameageyou searched with. A child searched as 9 must be booked as 9. - Order within a room doesn't matter, but every room must have exactly the adults and child ages you searched.
If the list doesn't match, the booking is refused before anything is charged:
{
"data": null,
"meta": {},
"error": {
"code": "traveler_manifest_mismatch",
"message": "Traveler manifest must match each searched room and contain 3 adult(s) and 2 child(ren) with the searched ages",
"details": []
}
}If the party has changed since the search, run a new search — prices can differ for a different party.
Always send the lead guest's email and phone
Some inventory can't be booked without a contact for the lead guest, and you can't tell from the rate which. Send both on travelers[0] for every booking. Without them some bookings return 400 supplier_contact_required.
Use the traveller's own contact details where you can. Hotels use them for arrival questions and changes on the day.
Real names only
Collect a real name for every guest before you book. Don't send placeholders such as “TBA”, “Guest 2” or the agent's own name: rooms and tickets are issued in the names you send, placeholders can be refused at check-in, and changing a name after booking isn't always possible.
Titles
Some inventory needs a title for the people it books, and refuses the booking without one. Send title as one of Mr, Mrs, Ms, Miss, Master or Dr:
- Hotels: on every traveller when the rate row or the price-checked quote has
requiresGuestTitle: true. - Activities and transfers: always on the lead traveller. The quote doesn't tell you which ones need it.
- Flights: on every passenger.
A missing or unrecognised title returns 400 traveler_title_required before anything is charged; message says which travellers need one. Collecting a title for everyone is the simplest way to never see it.
Nationality and residency
The search's residency is the lead guest's passport country, and the booking's lead nationality should be the same. The API doesn't check this for you. Some rates are only sold to certain nationalities, and the hotel may check. If the lead guest changes to someone with a different passport, search again with the new residency.
Traveller fields
Only the fields below are accepted; anything else is rejected with 400 validation_error. Some product-specific fields are checked before anything is charged — titles, and for some flights the passport details — but not all of them for every rate. Always send every field your product needs (below); otherwise the booking can fail.
| Field | Description |
|---|---|
firstNamestring, 1–60required | Given name as it appears on the traveller's ID. |
lastNamestring, 1–60required | Family name as it appears on the traveller's ID. |
emailstringlead traveller | Send on travelers[0]. Some inventory requires it and passes it to the hotel; without it those bookings return 400 supplier_contact_required. |
phonestringlead traveller | Send on travelers[0], in international format, e.g. +447700900123. Required by the same inventory as email. |
roomIndexinteger, 0–8 | Which room this guest sleeps in, counting from 0 in the order of your search's occupancy. Defaults to 0. |
type"adult" | "child" | "infant" | Defaults to adult. Send child for every guest searched as a child. Use infant only for activities; for hotels, send infants as children with their age. |
ageinteger, 0–120children | Required for children; must match the age you searched with. Activities also need it for adults (18–120). |
nationalityISO 3166-1 alpha-2flights | Passport country. Send it for every flight passenger. For hotels, send it on the lead traveller; it should match the search's residency (the API doesn't check this). |
titlestring, 1–8see below | One of Mr, Mrs, Ms, Miss, Master, Dr (any case; a trailing dot is fine). Required on every traveller when a hotel quote has requiresGuestTitle: true, and on the lead traveller for activities and transfers; send it for every flight passenger. See Titles. |
dateOfBirthYYYY-MM-DDflights | Send it for every flight passenger. Validate the format yourself; some flights refuse a missing or unreadable date with 400 travel_documents_required. |
gender"m" | "f"flights | Send it for every flight passenger. |
passportNumberstring, 1–20flights | Send it for every flight passenger, domestic journeys included. |
passportExpiryYYYY-MM-DDflights | Send it for every flight passenger. Validate the format yourself. Passports that expire within 6 months of travel can be refused with 400 travel_documents_required. |
carrierNamestring, 1–60some transfers | The flight's airline, when a transfer returns requiresFlightDetails: true. See Transfers. |
flightNumberstring, 1–7some transfers | The flight number, e.g. EK003. |
flightTimeHH:MM | The flight's local time. Kept for our operations team; it isn't passed to the operator. |
What each product needs
| Product | Every traveller | Lead traveller also |
|---|---|---|
| Hotels | Name; roomIndex; type and age for children; title when the quote has requiresGuestTitle: true | Email, phone, nationality |
| Flights | Name, title, dateOfBirth, gender, passportNumber, passportExpiry, nationality | Email, phone |
| Activities | Name; age for every adult (18–120) and child | Email, phone, title |
| Transfers | Name | Email, phone, title; the flight when required |
Hotel special requests
For hotels you can pass the guests' requests with the booking in hotelPreferences:
specialRequest— a note for the whole booking, up to 500 characters.rooms[]— per room:roomIndex(as on the travellers),smoking(boolean) andspecialRequest(up to 500 characters).
These are requests, not guarantees. They are passed to the hotel where the rate supports them; some inventory takes only one note for the whole booking, and a smoking preference isn't passed on everywhere. Don't promise a request to the traveller, and don't use it for anything the stay depends on — book a room type that includes it instead. Other products ignore hotelPreferences.