Hotels
Through the Wego API, you can search Hotels for a given location and dates. The search endpoint will give you all the available hotels upon search request. You must then poll to get the best rates for each hotel.
Rate is the object that contains the Price per Provider. For a better understanding of the Rate object and it's attributes, see the full description in References Section.
By default, the search result only returns one rate per hotel - which is the best rate for that hotel. There is another endpoint for getting all the available rates for a given hotel.
We highly recommend that you use our SDK. You can use it to trigger search, fetch results, filter and/or sort the results easily. If for some reason you can't use it, please follow along our guide below. We are also welcome to start an open source SDK in the language of your preference. Please contact us and we will help you.
Initiating a Search
You need to build the search object based from the user's input and settings. Here is an example request from a user searching an accomodation for their trip to London.
Headers:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Body:
{
"search": {
"siteCode": "SG",
"locale": "en",
"currencyCode": "SGD",
"cityCode": "LON",
"roomsCount": "1",
"guestsCount": "4",
"checkIn": "2017-12-19",
"checkOut": "2017-12-31",
"deviceType": "DESKTOP",
"appType": "WEB_APP",
"userLoggedIn": false
},
"offset": 0
}
The endpoint will give you a Search ID. This will be used as a reference for getting the hotels and rates on the succeeding calls.
Response
{
"search": {
"id": "fda81f1374870dfe",
"searchType": "CITY",
"city": {
"code": "LON",
"name": "London"
},
"worldRegion": {
"code": "e",
"name": "Europe"
},
"country": {
"code": "GB",
"name": "United Kingdom"
},
"roomsCount": 1,
"guestsCount": 2,
"checkIn": "2017-12-20",
"checkOut": "2018-01-03",
"createdAt": "2017-09-18T16:08:34.306Z",
"locale": "en",
"siteCode": "SG",
"currencyCode": "SGD",
"deviceType": "DESKTOP",
"appType": "WEB_APP",
"userCountryCode": "SG",
"key": "LON~CITY~2017-12-20~2018-01-03~1~2~SG~en~DESKTOP~WEB_APP",
"cityCode": "LON",
"cityName": "London",
"countryCode": "GB",
"countryName": "United Kingdom"
},
"hotels": [
{
"id": 155011,
"name": "Comfort Inn Kensington",
"star": 2,
"images": [
{
"url": "http://res.cloudinary.com/wego/image/upload/v1480302749/hotels/155011/12440473.jpg"
},
{
"url": "http://res.cloudinary.com/wego/image/upload/v1395058553/hotels/427238/12628696.jpg"
},
{
"url": "http://res.cloudinary.com/wego/image/upload/v1395058553/hotels/427238/12628699.jpg"
}
],
"propertyTypeId": 1,
"brandId": 0,
"chainId": 0,
"districtId": 0,
"imagesCount": 6,
"amenityIds": [],
"longitude": -0.197325,
"latitude": 51.494118
}
],
"propertyTypes": [
{
"id": 1,
"name": "Hotel"
}
],
"brands": [
{
"id": 48,
"name": "Best Western"
}
],
"chains": [
{
"id": 1008,
"name": "GLH Hotels"
}
],
"districts": [
{
"id": 2049,
"name": "Southwark"
}
],
"amenities": [
{
"id": 1,
"name": "Highspeed Internet"
}
]
}
The response also contains 20 hotels. These are the highest ranking hotels in London. Wego is returning these so you can show something to the user while Wego is working on the background to search for the best prices. Showing these hotels immediately have been proven to improve the user experience for us. Though, you are free to ignore this and move on to the next step to get all the hotels.
Getting the Search Results
You need to start polling to get more hotels and its best rates. Let's make the first poll.
Use the search ID returned in the previous step. Pass offset with value 0. We'll discuss what offset is for in the later section of this guide.
URL: https://affiliate-api.wego.com/metasearch/hotels/searches/:searchID?offset=0&locale=EN&currencyCode=SGD
Headers:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
URL Params:
offset: 0
locale: EN
currencyCode: SGD
Although this is the same endpoint, by sending the search ID instead of the search information, Wego recognises that this call is to get the results of this particular search.
Here's a snippet of the response.
Response: HTTP 200
{
"search": {
"id": "8d6b52983a64ebd9",
"searchType": "CITY",
"city": {
"code": "LON",
"name": "London"
},
"worldRegion": {
"code": "e",
"name": "Europe"
},
"country": {
"code": "GB",
"name": "United Kingdom"
},
"roomsCount": 1,
"guestsCount": 2,
"checkIn": "2017-12-19",
"checkOut": "2018-01-02",
"createdAt": "2017-09-18T05:09:33.733Z",
"locale": "en",
"siteCode": "SG",
"currencyCode": "SGD",
"deviceType": "DESKTOP",
"appType": "WEB_APP",
"userCountryCode": "SG",
"key": "LON~CITY~2017-12-19~2018-01-02~1~2~SG~en~DESKTOP~WEB_APP",
"cityCode": "LON",
"cityName": "London",
"countryCode": "GB",
"countryName": "United Kingdom"
},
"rates": [
{
"id": "8d6b52983a64ebd9:hotel.info:154581:178",
"hotelId": 154581,
"providerHotelId": "270932",
"providerCode": "hotel.info",
"createdAt": "2017-09-18T05:09:33.733Z",
"description": "Standard Double Room - Nonflex Hot Deal",
"price": {
"amount": 319,
"currencyCode": "SGD",
"amountUsd": 237.27838,
"taxAmount": 744.13104,
"taxAmountUsd": 553.6496,
"taxInclusive": true,
"ecpc": 0.67,
"localTaxAmount": -1,
"totalAmount": 4466,
"totalAmountUsd": 3321.8975
},
"rateAmenityIds": [
4
],
"handoffUrl": "http://handoff.wegostaging.com/hotels/continue/154581/405/178?search_id=8d6b52983a64ebd9&site=www.wego.com.sg&locale=en&version=2&device_type=DESKTOP&app_type=WEB_APP"
}
],
"hotels": [
{
"id": 154581,
"name": "Royal Park Hotel",
"star": 5,
"images": [
{
"url": "http://res.cloudinary.com/wego/image/upload/v1481138017/hotels/154581/14297751.jpg"
},
{
"url": "http://res.cloudinary.com/wego/image/upload/v1481138017/hotels/154581/14297757.jpg"
},
{
"url": "http://res.cloudinary.com/wego/image/upload/v1481138014/hotels/154581/2401523.jpg"
}
],
"propertyTypeId": 1,
"brandId": 463,
"chainId": 0,
"districtId": 2043,
"imagesCount": 57,
"amenityIds": [
1,
3,
4,
6,
7,
9,
10,
11,
12,
20
],
"longitude": -0.1763,
"latitude": 51.5142
}
],
"filter": {
"minPrice": {
"amount": 86,
"currencyCode": "SGD",
"amountUsd": 64.10319,
"taxAmount": 201.03157,
"taxAmountUsd": 149.57184,
"taxInclusive": true,
"ecpc": 0.67,
"localTaxAmount": 0,
"totalAmount": 1204,
"totalAmountUsd": 897.44464
},
"maxPrice": {
"amount": 752,
"currencyCode": "SGD",
"amountUsd": 559.7779,
"taxAmount": 1755.5186,
"taxAmountUsd": 1306.1438,
"taxInclusive": true,
"ecpc": 0.67,
"localTaxAmount": -1,
"totalAmount": 10528,
"totalAmountUsd": 7836.8906
},
"rateAmenities": [
{
"code": "1",
"count": 33
},
{
"code": "4",
"count": 36
},
{
"code": "5",
"count": 28
}
],
"brands": [
{
"code": "33",
"count": 1
},
{
"code": "103",
"count": 1
}
],
"chains": [],
"propertyTypes": [
{
"code": "1",
"count": 97
},
{
"code": "2",
"count": 1
}
],
"districts": [
{
"code": "1601",
"count": 2
},
{
"code": "2049",
"count": 4
},
{
"code": "5475",
"count": 1
}
],
"amenities": [
{
"code": "1",
"count": 45
},
{
"code": "2",
"count": 2
},
{
"code": "3",
"count": 16
}
],
"reviewerGroups": [
{
"code": "COUPLE",
"count": 31
},
{
"code": "BUSINESS",
"count": 6
},
{
"code": "SOLO",
"count": 24
},
{
"code": "ALL",
"count": 34
},
{
"code": "FAMILY",
"count": 27
}
],
"stars": [
{
"code": "2",
"count": 8
},
{
"code": "3",
"count": 37
},
{
"code": "4",
"count": 51
},
{
"code": "5",
"count": 8
}
]
},
"providerRatesCounts": [
{
"hotelId": 154581,
"providerCode": "hotel.info",
"ratesCount": 4
}
],
"propertyTypes": [
{
"id": 1,
"name": "Hotel"
},
{
"id": 2,
"name": "Hostel / Backpacker"
},
{
"id": 4,
"name": "Serviced Apartment"
},
{
"id": 5,
"name": "Resort"
}
],
"stars": [
{
"id": 1,
"name": "1"
},
{
"id": 2,
"name": "2"
},
{
"id": 3,
"name": "3"
},
{
"id": 4,
"name": "4"
},
{
"id": 5,
"name": "5"
}
],
"brands": [
{
"id": 173,
"name": "Leading Hotels of the World"
},
{
"id": 463,
"name": "Park Hotel Group"
},
{
"id": 48,
"name": "Best Western"
}
],
"chains": [],
"districts": [
{
"id": 2042,
"name": "Hammersmith and Fulham"
},
{
"id": 2043,
"name": "Westminister"
},
{
"id": 2060,
"name": "Tower Hamlets"
}
],
"amenities": [
{
"id": 1,
"name": "Highspeed Internet"
},
{
"id": 3,
"name": "Parking"
},
{
"id": 4,
"name": "Restaurant"
}
],
"rateAmenities": [
{
"id": 1,
"code": "BREAKFAST_INCLUDED",
"name": "Breakfast Included"
},
{
"id": 4,
"code": "FREE_WIFI",
"name": "Free WiFi"
},
{
"id": 5,
"code": "PAY_LATER",
"name": "Pay Later"
}
],
"providers": [
{
"code": "hotel.info",
"name": "HOTEL INFO",
"type": "OTA",
"id": 405,
"isMobileFriendly": true,
"isHotelWebsite": false
}
],
"count": 213
}
To check out the full defaults the objects and its attributes included in the response body, please refer to Reference page.
Understanding the Response
This response is a subset of the entire search result. It is important to understand that you can start showing this subset to the user so they can start interacting
Looking up for details
You might notice that most of the objects contain references ( ID or Code) to another object from another list. Our API uses this pattern for data that can be referenced by multiple objects - to avoid data duplication and to trim down size.
Displaying the results
As previously noted, you don't have to keep your users waiting to finish all the poll requests before showing the hotels. Use the the available hotels and rates now to engage your user. In the background, you can continue polling.
Polling for more results
You need to make another request to get the next set of result.
Supposed that the first response returned count with a value 100, you will use this as an offset for the succeeding request.
You are telling Wego that the next request you only want the 101st rates and onwards. Wego will not return the first 100 rates that was already returned in the previous poll.
URL: https://affiliate-api.wego.com/metasearch/hotels/searches/:searchID?offset=0&locale=EN&currencyCode=SGD
Headers:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
URL Params:
offset: 100
locale: EN
currencyCode: SGD
Merging multiple results
Using count and offset means that you are getting the results by chunk. This approach is good for performance because the size being passed over the network is significantly lower.
This means that the responses have to be merged carefully. Collections like amenities, brands, chains, districts, propertyTypes, etc need to be merged and deduped. ie: a district can appear on multiple responses.
You will also need to sort the hotels by rates when merging. The new rates might have cheaper prices than the previously returned rates.
Polling strategy
We recommend that you keep polling for more results with increasing intervals in between.
For example
- Poll #1 - wait 500ms before doing another poll
- Poll #2 - wait 1 second before doing another poll
- Poll #3 - wait 2 seconds before doing another poll
- Poll #4 - wait 3 seconds before doing another poll
- Poll #5 - wait 4 seconds before doing another poll
When to stop polling
If for three consecutive polls returned the same count, it means that the API has given all the available fares for this particular session. On average, it takes about 7 polls to get the entire results for a particular search session.
Filtering
The filter data is provided by the API. You can see several options under filters object in the response.
We are giving you the responsibility to filter the results. This means that when user changed a filter option, you will have to filter the results in the client. This main benefit of this approach is performance. You don't need to make another network call to filter the search result.
Sorting
Sorting is also done client-side. You can implement several sorting options. eg: by price, by rating, distance to airport/city center, etc.
Pagination
Pagination is also done client-side. You just need to slice the result based on your needs.
Getting more Rates
The search results only give you a single Rate per hotel. To get all the available rates for a hotel. You need to call another endpoint. This endpoint will give you rates from different providers in varying prices.
This endpoint is particularly useful when user shows interest on a particular hotel (by clicking of focusing on it), you can call this endpoint and show more rates.
{
"search": {
"id": "8d6b52983a64ebd9"
}
}