Introduction
Why did we build Travel Insight (TI) API?
Travel Insight (TI) Aggregation API is driven by our partners' need to connect to a significantly easier alternative to the traditional, ad-hoc approaches of data collection and data analysis.
What is it?
Travel Insight (TI) Aggregated API is a public API that enables subscribed partners to get an aggregated result of search and redirect data based on a set of queries.
Why Use it?
Instant Results
There’s no additional data processing required, unlike with raw data files.
Easy Accessibility
It’s easy to use and simple to plug into your Power BI tools.
How does it work?
For a given Origin and Destination itinerary, Travel Insight API parses previously searched itineraries across an array of specified dates. The service is highly customisable and offers unsurpassed search criteria, including filtering such as multiple lengths of stay, number of stops, day of week, departure/arrival time window, etc.
Aggregation API provides two endpoints to submit analytics queries:
/searches: runs analytical query on searches data
/exits: runs analytical query on exits (redirects) data
You’ll find an in-depth explanation of both endpoints later in this document.
Some questions API will help answer
- Which were the most searched destinations from Nice in Nov 2020?
- Where were people flying to from Madrid during Oct 2020 and Jan 2020?
- What’s the probability that travellers will choose one flight over another (search-redirect tie-in)?
- For a given set of unique filter combinations (and/or), what’s the average exit fare in a given shop day or period?
- For a given set of unique filter combinations (and/or), what’s the average number of travellers choosing a specific route?
- Which were the most searched destinations from a given origin such as Nice in Nov 2020, or any period selected?
- Where were people flying to from an origin such as Madrid during Oct 2020 and Jan 2020?
Scope of API
Supported Dimensions (used in both filters and groupBy query parameter)
On searches data:
- market: Name of the country user has selected or Skyscanner domain being used
- originCountry: The country of the first leg's first segment
- destinationCountry: The destination country of the first leg's last segment
- originIATA: Origin IATA airport code
- destinationIATA: Destination IATA airport code
- cabinClass: Cabin class type, either ECONOMY, BUSINESS, PREMIUMECONOMY, FIRST
- departureDate: Departure date
- returnDate: Return date
- pax: Passenger count
- route: The first leg's origin city concatenated with the final leg's destination city.
- kind: Trip type. Either 'RETURN', 'ONE_WAY' or 'MULTI_CITY'
- daysBeforeTravel: How many days before travel the search happened
- travelMonth: Date of travel of the oubound leg in the format YYYYMM
- dayOfWeek: Day of the week of the oubound leg (Monday is 1)
- lengthOfTripInDays: Difference in days between the outbound and return leg of the trip
- travelType: One of DOMESTIC or INTERNATIONAL
- userCityLatitude: Latitude of the user location
- userCityLongitude: Longitude of the user location
- userCityName: City name of the user
- userCountryCode: Country code of the user
- userRegionName: Region name of the user
- distanceToOriginInMetres: Distance in meters between the user location and the departing airport
- subscription.included: Markets and routes included in your subscription. "*" means "anything".
On exits(redirects) data:
- market: Name of the country user has selected or Skyscanner domain being used
- originCountry: The country of the first leg's first segment
- destinationCountry: The destination country of the first leg's last segment
- originIATA: Origin IATA airport code
- destinationIATA: Destination IATA airport code
- cabinClass: Cabin class type, either ECONOMY, BUSINESS, PREMIUMECONOMY, FIRST
- departureDate: Departure date- returnDate: Return date
- departureTimeOfDay: Departure time of day. Either 'EARLY_MORNING', 'MORNING', 'AFTERNOON', 'EVENING'. Early Morning (0000 to 0600), Morning (0600 to 1200), Afternoon (1200 to 1800), Evening (1800 to 2400)
- returnTimeOfDay: Return time of day. Either 'EARLY_MORNING', 'MORNING', 'AFTERNOON', 'EVENING'. Early Morning (0000 to 0600), Morning (0600 to 1200), Afternoon (1200 to 1800), Evening (1800 to 2400)
- kind: Trip type. Either 'RETURN', 'ONE_WAY' or 'MULTI_CITY'
- stops: Number of stops
- route: The first leg's origin city concatenated with the final leg's destination city.
- pax: Passenger count
- journeyDuration: Journey duration in minutes
- departureTimeOfDay: One of MORNING, AFTERNOON, EVENING for the outbound leg
- returnTimeOfDay: One of MORNING, AFTERNOON, EVENING for the return leg
- marketingCarriers: List of carriers on the itinerary selected
- daysBeforeTravel: How many days before travel the redirect happened
- travelMonth: Date of travel of the oubound leg in the format YYYYMM
- dayOfWeek: Day of the week of the oubound leg (Monday is 1)
- firstMarketingCarrier: First carrier on the selected itinerary
- lengthOfTripInDays: Difference in days between the outbound and return leg of the trip
- travelType: One of DOMESTIC or INTERNATIONAL
- userCityLatitude: Latitude of the user location
- userCityLongitude: Longitude of the user location
- userCityName: City name of the user
- userCountryCode: Country code of the user
- userRegionName: Region name of the user
- distanceToOriginInMetres: Distance in meters between the user location and the departing airport
- subscription.included: Markets and routes included in your subscription. "*" means "anything".
Supported Aggregations
On searches data
- count: Total number of rows matching given groupby combinations
On redirects data
- count: Total number of rows matching given groupby combinations
- averageFarePerPax: Average fare price in USD per pax for rows matching given groupby combinations (can only be used alongside
count
)
Sorting
Results are sorted by the count value (descending)
Supported Query Criteria
- Max number of
filter
s allowed in a query: 11 - Max number of dimensions allowed in a
groupBy
query parameter: 4 - Max date interval supported in a query: 30 days, by default
- Max number of queries allowed in a minute: 50
- Partner's API key must be available in
API-Key
request header - Data is available from 2018-01-01, by default.
- Maximum number of results returned in an API call is 100000 and the API does not support paging at this stage.
- Be aware that searches can be done on a city or airport level. Consider this when using the originIATA or destinationIATA filters. eg all searches for London should use the followings values: LHR, LCY, LGW, LTN, SEN (airport codes) and LON (IATA code for the city)
Authentication
API Key Based Authentication
Security scheme type: | API Key |
Header parameter name: | API-Key |
Aggregation API
API to serve analytical queries over searches and exits
- Production Server base URL: https://www.skyscanner.net/g/travel-insight-api/api/aggregation
Aggregated Exits
POST /exits
Request samples
{
"startDate": "string",
"endDate": "string",
"filter": "string",
"groupBy": ["string"],
"aggregations": ["count", "averageFarePerPax"]
}
Response samples
{
"results": [
{
"dimensions": [
{
"name": "market",
"value": "SG"
}
],
"aggregations": [
{
"name": "count",
"value": "123"
},
{
"name": "averageFarePerPax",
"value": "765.43"
},
]
}
],
"subscription": {
"included": [
{
"market": "ES",
"origin": "BCN",
"destination": "*"
}
]
}
}
/exits endpoint supports 2 types of queries
group by date
- For this type of query users don’t have to provide any dimension in groupBy query parameter.
- Returned response will have results grouped by date
- Example:
Request:
curl -X POST https://www.skyscanner.net/g/travel-insight-api/api/aggregation/exits
with JSON body:
{
"startDate": "2020-12-25",
"endDate": "2020-12-26",
"filter": "{market=SG}"
}
and your API-Key set in request headers.
===========================================
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
"results": [
{
"dimensions": [
{
"name": "date",
"value": "2020-12-25",
}
],
"aggregations": [
{
"name": "count",
"value": 1500
}
]
},
{
"dimensions": [
{
"name": "date",
"value": "2020-12-26",
}
],
"aggregations": [
{
"name": "count",
"value": 2000
}
]
}
]
}group by multiple dimension (supported: 3 max)
- For this type of query users can specify up to 3 dimensions in groupBy query
- Returned response will have results grouped by provided dimensions
- Example:
Request:
curl -X POST https://www.skyscanner.net/g/travel-insight-api/api/aggregation/exits
with JSON body:
{
"startDate": "2020-12-25",
"endDate": "2020-12-26",
"filter": "{market=SG}",
"groupBy": ["originIATA", "destinationIATA"]
}
and your API-Key set in request headers.
===========================================
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
"results": [
{
"dimensions": [
{
"name": "originIATA",
"value": "LHR",
},
{
"name": "destinationIATA",
"value": "CDG",
}
],
"aggregations": [
{
"name": "count",
"value": 2134
}
]
},
{
"dimensions": [
{
"name": "originIATA",
"value": "SIN",
},
{
"name": "destinationIATA",
"value": "LHR",
}
],
"aggregations": [
{
"name": "count",
"value": 2000
}
]
},
{
"dimensions": [
{
"name": "“originIATA”",
"value": "CDG",
},
{
"name": "“destinationIATA”",
"value": "LHR",
}
],
"aggregations": [
{
"name": "count",
"value": 1200
}
]
}
]
}
In both type of queries only startDate
and endDate
are mandatory query parameters.
filter
and groupBy
query parameters, on the other hand, are optional.
Supported filter format can be expressed with the following grammar:
EBNF grammar for filter structure:
<filter> ::= "{" <fieldTokens> ("," <fieldTokens>)* "}";
<fieldTokens> ::= <fieldName> "=" <fieldValue> | <fieldRangeToken>;
<fieldRangeToken> ::= <fieldName> ("<" | "<=" | ">" | ">=") <value>;
<fieldValue> ::= valueToken;
<valueToken> ::= <value> | "(" <value> (<operator> valueToken)* ")"
<operator> ::= "|";
<fieldName> ::= "originCountry" | "destinationCountry" | "originIATA" | "destinationIATA" | "market"
| "cabinClass" | "departureDate" | "returnDate" | "pax" | "journeyDuration" |"route" | "kind" | "departureTimeOfDay"
| "returnTimeOfDay" | "marketingCarriers" | "stops" ;
<value> ::= string | integer | date | datetime;
Semantics:
<operator> "|" represents logical OR (||)
EBNF syntax: * for "zero or more" occurrences
Range operators allowed only for pax, stops, departureDate, returnDate, journeyDuration
Example: filter={market=(UK|FR),originIATA=LHR,destinationIATA=(CDG|ORY),pax>1,pax<=5}
Please note that there should not be any spaces between filter tokens
Responses
Code | Description |
---|---|
200 | Aggregated results returned |
400 | Request validation failure - Invalid input syntax |
401 | Unsuccessful authentication |
422 | Request validation failure - Malformed semantics in input |
429 | Too many requests |
500 | Failure to process the request |
Aggregated Searches
POST /searches
Request samples
{
"startDate": "string",
"endDate": "string",
"filter": "string",
"groupBy": ["string"],
"aggregations": ["count"]
}
Response samples
{
"results": [
{
"dimensions": [
{
"name": "market",
"value": "SG"
}
],
"aggregations": "count",
"subscription": {
"included": [
{
"market": "ES",
"origin": "BCN",
"destination": "*"
}
]
}
}
]
}
/searches endpoint supports 2 types of queries
group by date
- For this type of query users don’t have to provide any dimension in groupBy query parameter.
- Returned response will have results grouped by date
- Example:
Request:
curl -X POST https://www.skyscanner.net/g/travel-insight-api/api/aggregation/exits
with JSON body:
{
"startDate": "2020-12-25",
"endDate": "2020-12-26",
"filter": "{market=SG}"
}
and your API-Key set in request headers.
===========================================
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
"results": [
{
"dimensions": [
{
"name": "date",
"value": "2020-12-25",
}
],
"aggregations": [
{
"name": "count",
"value": 1500
}
]
},
{
"dimensions": [
{
"name": "date",
"value": "2020-12-26",
}
],
"aggregations": [
{
"name": "count",
"value": 2000
}
]
}
]
}group by multiple dimension (supported: 3 max)
- For this type of query users can specify up to 3 dimensions in groupBy query
- Returned response will have results grouped by provided dimensions
- Example:
Request:
curl -X POST https://www.skyscanner.net/g/travel-insight-api/api/aggregation/exits
with JSON body:
{
"startDate": "2020-12-25",
"endDate": "2020-12-26",
"filter": "{market=SG}",
"groupBy": ["originIATA", "destinationIATA"]
}
and your API-Key set in request headers.
===========================================
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
{
"results": [
{
"dimensions": [
{
"name": "originIATA",
"value": "LHR",
},
{
"name": "destinationIATA",
"value": "CDG",
}
],
"aggregations": [
{
"name": "count",
"value": 2134
}
]
},
{
"dimensions": [
{
"name": "originIATA",
"value": "SIN",
},
{
"name": "destinationIATA",
"value": "LHR",
}
],
"aggregations": [
{
"name": "count",
"value": 2000
}
]
},
{
"dimensions": [
{
"name": "“originIATA”",
"value": "CDG",
},
{
"name": "“destinationIATA”",
"value": "LHR",
}
],
"aggregations": [
{
"name": "count",
"value": 1200
}
]
}
]
}
In both type of queries only startDate
and endDate
are mandatory query parameters.
filter
and groupBy
query parameters, on the other hand, are optional.
Supported filter format can be expressed with the following grammar:
EBNF grammar for filter structure:
<filter> ::= "{" <fieldTokens> ("," <fieldTokens>)* "}";
<fieldTokens> ::= <fieldName> "=" <fieldValue> | <fieldRangeToken>;
<fieldRangeToken> ::= <fieldName> ("<" | "<=" | ">" | ">=") <value>;
<fieldValue> ::= valueToken;
<valueToken> ::= <value> | "(" <value> (<operator> valueToken)* ")"
<operator> ::= "|";
<fieldName> ::= "originCountry" | "destinationCountry" | "originIATA" | "destinationIATA"
| "market" | "cabinClass" | "departureDate" | "returnDate" | "pax" | "route" | "kind" ;
<value> ::= string | integer | date | datetime;
Semantics:
<operator> "|" represents logical OR (||)
EBNF syntax: * for "zero or more" occurrences
Range operators allowed only for pax, departureDate, returnDate
Example: filter={market=(UK|FR),originIATA=LHR,destinationIATA=(CDG|ORY),pax>1,pax<=5}
Please note that there should not be any spaces between filter tokens
Responses
Code | Description |
---|---|
200 | Aggregated results returned |
400 | Request validation failure - Invalid input syntax |
401 | Unsuccessful authentication |
422 | Request validation failure - Malformed semantics in input |
429 | Too many requests |
500 | Failure to process the request |