It will be hot this summer in Montreal with the Osheaga festival! Your challenge is to build a microsite that allows a traveler from NYC to find one-way departure schedules for the festival's opening weekend.
- Has a simple onboarding screen that will trigger the departure search
- Lists all the departures for a given origin city (New York - geohash: dr5reg) and a given destination city (Montréal - geohash: f25dvk) for a given day (the 29th of July 2017) for 1 adult.
- For each departure, we want, at least, to see the departure time, the arrival time, the location name and the price (use
prices.total
of thedeparture
).
- The code should be hosted on github, and the repo should be shared with Busbud and submitted as a pull request
- The microsite should be deployed to Heroku.
- Localization: support for multiple languages (English, French, ...)
- Responsive design
- You can setup your microsite any way you like; we're partial to NodeJS, ExpressJS and React
- CSS can be written using SASS, LESS or similar higher-level language
- All API requests need a special
X-Busbud-Token
HTTP Header, which you should have received with your challenge - All API requests need a special
Accept
HTTP Header, as described below
For all these requests, you MUST change the Accept header to:
application/vnd.busbud+json; version=2; profile=https://schema.busbud.com/v2/
Search is performed in two steps
- A search is initialized, and may be complete if results are served from cache
- An initialized and incomplete search is polled until complete
To get departures, search is initialized via the following endpoint:
https://napi.busbud.com/x-departures/:origin/:destination/:outbound_date
Path parameters:
origin
: Origin's geohashdestination
: Destination's geohashoutbound_date
: ISO 8601 Outbound departure date
Querystring parameters:
adult
: Number of adultschild
: Number of childrensenior
: Number of seniorslang
: ISO 3166-1 alpha-2 language codecurrency
: ISO 4217 currency code
The response looks like:
{
"origin_city_id": "375dd5879001acbd84a4683dedf9eed1",
"destination_city_id": "375dd5879001acbd84a4683ded9c875b",
"cities": [
{ City },
{ City }
],
"locations": [
{ Location }
{ Location }
],
"operators": [
{ Operator },
{ Operator }
],
"departures": [
{ XDeparture },
{ XDeparture }
],
"complete": false,
"ttl": 900,
"is_valid_route": true
}
Where a City is like:
{
"id": "375dd5879001acbd84a4683deda84183",
"locale": "en",
"region_id": 6417,
"name": "New York",
"lat": 40.71427,
"lon": -74.00597,
"geohash": "dr5reg",
"timezone": "America/New_York",
"image_url": "/images/promos/city-blocks/new-york.jpg",
"legacy_url_form": "NewYork,NewYork,UnitedStates",
"full_name": "New York, New York, United States",
"region": {
"id": 6417,
"locale": "en",
"country_code2": "US",
"name": "New York",
"country": {
"code2": "US",
"locale": "en",
"code3": "USA",
"name": "United States",
"continent": "NA",
"default_locale": "en",
"default_currency": "USD",
"population": 310232863
}
}
}
Where a Location is like:
{
"id": 3970,
"city_id": "375dd5879001acbd84a4683dedfb933e",
"name": "Métro Bonaventure Bus Station",
"address": [
"997 Rue St-Antoine Ouest",
"Montreal, QC H3C 1A6"
],
"type": "transit_station",
"lat": 45.4988273060484,
"lon": -73.5644745826722,
"geohash": "f25dvfzcz"
}
Where an Operator is like:
{
"id": "bfc27cd544ca49c18d000f2bc00c58c0",
"source_id": 155,
"profile_id": 111,
"name": "Greyhound",
"url": null,
"logo_url": "https://busbud-pubweb-assets-staging.global.ssl.fastly.net/images-service/operator-logos/greyhound.png?hash=1{&height,width}",
"display_name": "Greyhound",
"sellable": true,
"fuzzy_prices": false,
"sell_tickets_cutoff": {
"hours": 1
},
"amenities": {
"classes": {
"Normal": {
"display_name": "Economy",
"wifi": true,
"toilet": true,
"ac": true,
"food": false,
"refreshment": false,
"power_outlets": true,
"tv": false,
"bus_attendant": false,
"leg_room": false
},
"Economy": {
"display_name": "Economy",
"wifi": true,
"toilet": true,
"ac": true,
"food": false,
"refreshment": false,
"power_outlets": true,
"tv": false,
"bus_attendant": false,
"leg_room": false
}
}
},
"source": "greyhound_us",
"referral_deal": false,
"display_url": null,
"fraud_check": "iovation",
"terms": {
"refund": false,
"exchange": true,
"bag_allowed": true,
"piece_of_id": false,
"boarding_requirement": "printed_tkt",
"extra_bag_policy": true,
"use_new_ticket": false,
"exchange_cutoff": 24,
"nb_checked_bags": 1,
"kg_by_bag": 25,
"nb_carry_on": 1,
"extra_bag_cost": 1500
}
}
And an XDeparture is :
{
"id": "7c5dd26a",
"source_id": 155,
"checkout_type": "new",
"operator_id": "bfc27cd544ca49c18d000f2bc00c58c0",
"origin_location_id": 1942,
"destination_location_id": 1938,
"class": "Economy",
"class_name": "Economy",
"amenities": {
"display_name": "Economy",
"wifi": true,
"toilet": true,
"ac": true,
"food": false,
"refreshment": false,
"power_outlets": true,
"tv": false,
"bus_attendant": false,
"leg_room": false
},
"available_seats": 55,
"prices": {
"total": 5200,
"breakdown": {
"base": 5200
},
"categories": {},
"discounted": false
},
"ticket_types": [
"print"
],
"departure_timezone": "America/New_York",
"arrival_timezone": "America/Montreal",
"departure_time": "2016-01-14T00:01:00",
"arrival_time": "2016-01-14T07:55:00"
}
While the complete
property from the response is false, you need to call:
https://napi.busbud.com/x-departures/:origin/:destination/:outbound_date/poll
with all the same parameters as the previous endpoint, plus the following additional querystring parameter:
index
: Index from which to return new departures
The response is similar to:
{
"departures": [
{ XDeparture },
{ XDeparture }
],
"operators": [
{ Operator },
{ Operator }
],
"complete": true,
"ttl": 900
}