API overview
Content
In the following chapters we will describe
- What is the reference architecture
- What access token / ids you need to call the API
- How to execute an autocomplete query
- How to call the trip planner from the autocomplete results
Reference architecture
Triplinx services are split into two main components:
- The Triplinx API
- Which includes trip-planning, timetables, routes detail, stops detail.
- The Triplinx API communicates with 3Scale, an API management solution.
- The Algolia API
- Which is an API targeting a single need: The autocomplete / Search of trip points (Stops, Streets, POI).
- Algolia has its own API management solution.
The recommended usage is to call the Triplinx API from your back end as its model is quite large and should be mapped to a model closer to your front end needs. It also have the benefit of hiding the access key within your backend and provide an easier way to compose different calls.
The Algolia API should instead be directly call from your front end for performance purposes:
- Client calls are distributed through several servers with the help of a load balancer
- If you call the Algolia API from a single IP (Your back end) you loose the benefit of the load balancer (Due to Algolia design choice).

Prerequisites
In order to access each web service you need to obtain:
- Triplinx API
- An
user_key
which is available on the Developer portal.- This key is used to call the Cityway APIs and identify the client.
- An
- Algolia API
API key
,Application Id
,Index Name
- These values identify the client and the targeted database
- These values are not available on the developer portal and should have been sent to you during your account creation. If not please contact Cityway.
Accessing Triplinx API
To obtain the user_key
please sign in on the developer portal with the credential you received:

Then use the applications tab to display your application(s). You should have a default app already created. This screen will display each application access key. (Note: If you want additional applications, you can request additional keys using the Create new application
button. (Staging / Production envs, Mobile / Web clients, ...))

This key must be added as a query parameter, user_key
, it must be the first one in the query string: http://.../.../method?user_key=xxx&another_parameter=yyy
).
Accessing Algolia
In order to use the Algolia functionality, you must gather the following information: the Application ID
, the API Key
, the Index Name
. These three values should have been sent to you, if not, please contact Cityway.
Once you have these values you can call Algolia API with two differents methods:
- The recommended method is to use Algolia provided clients, Algolia provide clients for a very large set of languages and technologies (JS, PHP, Rails, Django, ...)
- Implement your own client calling the Algolia REST API
For JavaScript usage, Algolia supports Cross-Origin Resource Sharing (CORS), so that you can use these headers in conjunction with XMLHttpRequest.
Auto complete / Searching trip points
Search request
The two following examples use the query "20 Bay Street Toronto". In real case usage the user will usually only input partial query like "20 bay s" and find his/hers expected result within the autocomplete proposal.
Here is an example using the Algolia JS client:
var client = algoliasearch('{Application Id}', '{API Key}');
var index = client.initIndex('{Index Name}');
index.search('20 Bay Street Toronto', function searchDone(err, content) {
if (err) {
console.error(err);
return;
}
for (var h in content.hits) {
console.log('Hit(' + content.hits[h].objectID + '): ' + content.hits[h].toString());
}
});
Here is an example using the Algolia REST API:
curl -X GET \
-H "X-Algolia-API-Key: {API Key}" \
-H "X-Algolia-Application-Id: {Application Id}" \
"https://{Application Id}-dsn.algolia.net/1/indexes/{Index Name}?query=20%20Bay%20Street%20Toronto"
Handling the search results
As a response to the previous request, you should receive a result object.
This is the JSON representation:
{
"hits" : [{
"TRIPPOINT_PK" : "12078-3-21055288",
"ID_TRIPPOINT" : 12078,
"NAME" : "Bay Street",
"SIMPLIFIEDNAME" : "BAY STREET",
"NAME_LENGTH" : 10,
"LOCALITYNAME" : "TORONTO",
"LOCALITYCODE" : "21055288",
"_geoloc" : {
"lng" : -79.38426404987403,
"lat" : 43.65710250001331
},
"STARTNUMROAD" : 11,
"ENDNUMROAD" : 1333,
"ROADLENGTH" : 4059,
"POINTTYPE" : 3,
"POICATEGORY" : null,
"WEIGHT" : 1.1158303790564494,
"TRANO" : null,
"TRANOM" : null,
"TRAIDTRANSPORTEUR" : null,
"STATIONCODE": null,
"ISSTATION" : 0,
"HASSTATIONTERM" : 0,
"NAMEWITHSN" : "<streetnumber1to100> Bay Street",
"LOCATIONS" : {
"11" : {
"lng" : -79.37705259277648,
"lat" : 43.641528997023116,
"calctype" : 0
},
"20" : {
"lng" : -79.37727683652372,
"lat" : 43.64186319151011,
"calctype" : 0
},
"27" : {...}, /* truncated */
"..." : {...}
},
"objectID" : "12078-3-21055288-0-1",
"_highlightResult" : {
"NAME" : {
"value" : "<em>Bay</em> <em>Street</em>",
"matchLevel" : "partial",
"fullyHighlighted" : true,
"matchingWords" : ["bay", "street"]
},
"SIMPLIFIEDNAME" : {
"value" : "<em>BAY</em> <em>STREET</em>",
"matchLevel" : "partial",
"fullyHighlighted" : true,
"matchingWords" : ["bay", "street"]
},
"LOCALITYNAME" : {
"value" : "<em>TORONTO</em>",
"matchLevel" : "partial",
"fullyHighlighted" : true,
"matchingWords" : ["toronto"]
},
"NAMEWITHSN" : {
"value" : "<em>20</em> <em>Bay</em> <em>Street</em>",
"matchLevel" : "partial",
"fullyHighlighted" : true,
"matchingWords" : ["20", "bay", "street"]
}
},
"_rankingInfo" : {
"nbTypos" : 0,
"firstmatchingWord" : 1000,
"proximityDistance" : 10,
"userScore" : 1,
"geoDistance" : 0,
"geoPrecision" : 1,
"nbExactWords" : 3,
"words" : 4,
"filters" : 0
}
}],
"nbHits" : 1,
"page" : 0,
"nbPages" : 1,
"hitsPerPage" : 10,
"processingTimeMS" : 3,
"facets" : {
"POINTTYPE" : {
"3" : 1
},
"LOCALITYNAME" : {
"TORONTO" : 1
}
},
"facets_stats" : {
"POINTTYPE" : {
"min" : 3,
"max" : 3,
"avg" : 3,
"sum" : 3
}
},
"exhaustiveFacetsCount" : false,
"exhaustiveNbHits" : true,
"query" : "20 Bay Street Toronto",
"params" : "query=20%20Bay%20Street%20Toronto&getRankingInfo=1&facets=*&attributesToRetrieve=*&highlightPreTag=%3Cem%3E&highlightPostTag=%3C%2Fem%3E&hitsPerPage=10&facetFilters=%5B%5D&maxValuesPerFacet=100",
"serverUsed" : "c4-fr-3.algolia.net",
"parsedQuery" : "20 bay street toronto"
}
The query which generated this result is "20 Bay Street Toronto".
The following section describes each field of that JSON data :
Field | Description |
---|---|
hits | The array of matching results |
nbHits | The number of matching results |
page | The requested results page |
nbPages | The total number of results pages |
hitsPerPage | The number of matching results per page |
processingTimeMS | The response processing time |
facets | The fields used to filter data on the index 1* |
facets_stats | Some stats about facets |
exhaustiveFacetsCount | Whether the counts of the facet values are exhaustive or approximate |
exhaustiveNbHits | Whether the nbHits is exhaustive or approximate |
query | The root user query |
params | The query parameters |
serverUsed | The server used to return results regarding to DSN |
parsedQuery | The parsed query |
1* The field "facets" maps each facet name to the corresponding facet counts
Understand the search result
The search results are stored in the JSON data under the "hits" property. It is an array of objects corresponding to trip points with specific locations along streets, roads...
Below is the description of a single object:
Field | Description |
---|---|
TRIPPOINT_PK | The trip point primary key |
ID_TRIPPOINT | The trip point identifier |
NAME | The trip point name |
SIMPLIFIEDNAME | The trip point simplified name |
NAME_LENGTH | The trip point name length |
LOCALITYNAME | The trip point locality name |
LOCALITYCODE | The trip point locality code |
_geoloc | The trip point geographic location (longitude and latitude) |
STARTNUMROAD | The trip point start number |
ENDNUMROAD | The trip point end number |
ROADLENGTH | The trip point road length |
POINTTYPE | The trip point type (1, 3 or 4) 1* |
POICATEGORY | The trip point POI category |
WEIGHT | The trip point weight |
TRANO | The trip point transporter number |
TRANOM | The trip point transporter name |
TRAIDTRANSPORTEUR | The trip point transporter identifier |
STATIONCODE | The station code if applicable. Is the stop_id column value from GTFS dataset. |
ISSTATION | Whether or not this trip point is a station |
HASSTATIONTERM | Whether or not this trip point has station terms |
NAMEWITHSN | The name with the right placeholder |
LOCATIONS | The geographic locations for each known street number on this trip point placeholder 2* |
objectID | The Algolia internal object identifier |
_highlightResult | The highlighted attributes if specified in the Algolia backend |
_rankingInfo | Some precisions about the ranking info of the matching result |
1* Three (3) trip points types are available in the database:
- 1 -> POI (Point of interest)
- 3 -> Road networks
- 4 -> Logical stops
2* A known street number with its exact location
"40" : {
"lng" : -79.379342176695,
"lat" : 43.64359329237533,
"calctype" : 0
}
40
is the street number, lng
is the longitude, lat
is the latitude and calctype
indicates whether this location was a single street number 0
or interpolated from a numbers range 1
.
What to do with results
With this JSON hits results, geographic positions per street numbers can be extracted to draw an itinerary by example. Both start and end points positions can be extracted according to their street numbers in the JSON data. All hits are sorted according to their ranks and reliability.
Case where no street number match the query
In case no street number match the query you can either use the 'closest' street number of the selected item or call the Triplinx API /api/map/v2/getroadsection/(xml|json)
to get an approximate location coordinates, to call this API you need:
ID_TRIPPOINT
which goes in theRoad
parameterNumber
where you put the researched road number your user inputed
Like this: http://apihost/api/map/v2/GetRoadSection/json?user_key=someKey&Road=12078&Number=20000
You will get a reply like this:
{
"Data": {
"Id": 12078,
"Latitude": 43.67310092174979,
"Locality": {
"Id": 21055288,
"InseeCode": "21055288",
"Latitude": 43.64856000024389,
"Longitude": -79.3853700002253,
"Name": "TORONTO"
},
"LocalityId": 21055288,
"Longitude": -79.39069142215777,
"Name": "Bay Street",
"PointType": 3,
"FirstNumber": 11,
"IdSection": 555972,
"LastNumber": 1333,
"Length": 4059,
"MaxOddNumber": 1333,
"MinOddNumber": 11,
"Number": 0
},
"Message": null,
"StatusCode": 200
}
Data.Latitude
&& Data.Longitude
are the values to use to call the trip planner.
Calling the trip planner
To call the trip planner you need the following mandatory values:
- A departure point AND an arrival point each one can be either
- A WGS84 latitude / longitude pair
- A
trip point id
with atype id
- An arrival OR a departure time
- If you specify an arrival time the trip planner will try to "Arrive at {arrival time}"
- A date
- An algorithm
FASTEST
(time optimization)SHORTEST
(distance optimization)MINCHANGES
(transfer count optimization)
- A list of authorised modes (
PT
Public Transport,CAR
,BIKE
)
There is also a couple of optional parameters, the most used being:
AllowedOperatorIds
: Constrain the trip planner to only use a sub set of the availables PT networks (Default: All)Modes
: Constrain the trip planner to use only this set of PT modes (TRAIN, BUS, ...) (Default: All)MaxWalkDistance
: Limit the walk distance
For a full listing, please consult the full API documentation.
Using the autocomplete result
{
"hits" : [{
"TRIPPOINT_PK" : "12078-3-21055288",
"ID_TRIPPOINT" : 12078,
"NAME" : "Bay Street",
// ...
"_geoloc" : {
"lng" : -79.38426404987403,
"lat" : 43.65710250001331
},
// ...
"POINTTYPE" : 3,
//..
"LOCATIONS" : {
//...
, "20" : {
"lng" : -79.37727683652372,
"lat" : 43.64186319151011,
"calctype" : 0
},
// "..." : {...}
},
// ...
}
}
From our previous query on Algolia (20 Bay street Toronto
) we extract the first word and as it is an integer we know that the road number is 20
, we look inside the LOCATIONS
collection and find LOCATIONS['20']
. From this item, we now have the latitude
and longitude
of the trip point.
For the departure, we will be using a stop point to demonstrate the usage of a different trip point type: Kitchener GO
Algolia query results are:
{
"hits": [
{
"TRIPPOINT_PK": "14413-4-21086187",
"ID_TRIPPOINT": 14413,
"STATIONCODE": "KI",
"NAME": "Kitchener GO",
"SIMPLIFIEDNAME": "KITCHENER GO",
"NAME_LENGTH": null,
"LOCALITYNAME": "KITCHENER",
"LOCALITYCODE": "21086187",
"_geoloc": {
"lng": -80.49313354492188,
"lat": 43.455684661865234
},
// ... ,
"POINTTYPE": 4,
// ... ,
"_highlightResult": { /* ... */ },
"_rankingInfo": { /* ... */ }
}, { /* ... */ }
],
// ...
}
Since the result is not an address (!= 3) we just need to extract the ID_TRIPPOINT
and POINTTYPE
.
We now have the following values:
- Departure
- DepartureType =
COORDINATES
- DepartureLatitude =
43.64186319151011
- DepartureLongitude =
-79.37727683652372
- DepartureType =
- Arrival
- ArrivalType =
STOP_PLACE
- Note: I've provided a translation table for converting from int value (
POINTTYPE
) to enum value used in the trip planner queries. It's at the end of the documentation try CTRL-FTripPointTypeId <=> TripPointTypeName
- Note: I've provided a translation table for converting from int value (
- TripPointId =
14413
- ArrivalType =
We can now launch a trip planner query from the developer portal once we picked missing parameters:
- Date =
2017-04-20_08-00
- Format is
yyyy-MM-dd_HH-mm
- Format is
- DateType =
DEPARTURE
- Our date value is a "Departure time"
- Algorithm =
FASTEST
- Try to optimize duration
- TripModes =
PT
- Public transport query

Useful mapping data
TripPointTypeId <=> TripPointTypeName
This table is useful for mapping Algolia POINTTYPE
to Triplinx API DepartureType
and ArrivalType
TripPointTypeId | TripPointName |
---|---|
1 | POI |
3 | ADDRESS |
4 | STOP_PLACE |
OperatorId <=> Operator Name
This table is useful to filter Triplinx API queries by OperatorIds
OperatorId | OperatorName |
---|---|
1 | GO Transit |
4 | TTC |
5 | York Region Transit |
6 | Milton Transit |
7 | Oakville Transit |
8 | Burlington Transit |
9 | Hamilton Street Railway |
10 | Brampton Transit |
11 | MiWay |
12 | Durham Region Transit |
20 | Up Express |
21 | Pearson Terminal Link |
23 | Toronto Ferries |