If you are not yet familiar with GraphQL and GraphiQL it is highly recommended to review those pages at first.
Term | Explanation |
---|---|
Itinerary | A combination of different transportation modes at certain times to reach from origin to destination. For example, walking to a bus stop, taking a bus for two stops and then walking to the final destination. Commonly used synonym: journey |
Leg | One part of an itinerary, e.g. walking to a bus stop or a bus ride between two stops. |
Origin | A geographical point where an itinerary begins. |
Destination | A geographical point where an itinerary ends. |
You can ask the server to return geometries for itineraries. The API will return them in Google polyline-encoded format. It looks like this:
"legGeometry": {
"length": 349,
"points": "wwfnJyjdwCXlAHLNfAFHDZz@nEh@hBXfA\\hAR^VLnChAD@HDHDjBt@^N|@`@JDHNFB`@RHDJFD@PD^fBDNNp@@JBPHl@FdA@d@@TFrCDnATpEL~CBnA@pADpELbQ?pB?nBC~@DdC?R?LDtC?P?j@@XG~@Ef@CPCHGHoAtAQT_@f@w@rAc@~@g@lAi@fBc@hBWvASzAWrBUtBQxBOtBMhCOvEEhCCfC@vB@fBDrCFlCJnCb@xIfFl_APdDr@dMd@bIV~D\\bFPnCjAtMt@~GxAhMlBfOz@jHVjCR~BNpCHrBFjCDdC?`CC`DIfDSxDUhDe@fFu@tHMzA{AlOcBtPCXE`@sCrY_BbPShCeAxJc@pDg@nECJi@~Di@dDUbAkA~Gk@bD_@vBUbB]lBe@lDY~B[rCWbC_@~DYfDW|BQ~Am@tGOfBOxAWlCKzAMvAIbAMpBIpAAd@GhACp@EhAEtAA~ACfCAnC@fA?rAClDC`G@`BCxHKlCMhIK~FE|CA~@@|@BxB@^?@DtAHbBLzALjBHbBFlAF|ADxAD|BNrEPjCTtHdAhVp@jSVlPFjJ?dC?hE?dJ?xC?vLDfKDpEF|CFnDPjHZvH\\xH|@jQXnF\\nFBXdAtSJtCZrG@^b@`K^dJLnDLtDj@bRT`IAb@?~@?dA@~A?fA?|@AjAE~BA`BBdABd@Bh@HfARnBPpBl@zFt@lGr@vE\\|Cz@dHrA|JdAtHPpAl@dEjA~I~AvNv@tIx@vKTtD`@nHTrENtDRzEPvHR|J\\`VNdKAjEFpLBlFDjCBfCFxBNjE`@nH@j@An@Cr@I^O^y@l@iAt@S@IAIGMKCICIKIKEI?MDILKVQVW^WVUPSJuAT??_ANaALg@No@ZkAz@a@ZKR]j@a@h@i@fA[f@Q`@u@dCmAvEw@dCk@nAe@z@S\\iAnAeA`Ai@f@eAfBy@rBu@rCMf@WfAU`Ac@`Bi@`CKh@ANUdBq@~GW|BQdAK^M\\IROVMLs@d@q@\\]P}@R{@BaA@_@Iu@E]?CAU?M?W@i@DKBg@NUDq@V}@^g@XQJk@h@EDQPeBnBIHILU\\"
}
Note: For more details about the query type planConnection and its parameters you can use the Documentation Explorer provided in GraphiQL.
Note: Some additional examples can be found on the Bicycles, cars and e-scooters page.
Itinerary planning can be tuned by multiple arguments of the planConnection query.
Time arguments are taken into account literally when planning the itinerary
preferences: {street: { transit: {transfer: {slack: "2m"}}}
, it is not possible to continue the journey by another vehicle within two minutes after disembarking one vehicleCost arguments on the other hand are not hard limits, but preferences
preferences: {street: {walk: {boardCost: 120}}}
, it is possible to continue the journey immediately after disembarking from one vehicle, but up to 2 minutes longer itineraries are preferred if they have one transfer less and up to 4 minutes longer itineraries are preferred if they have two transfers less, etc.boardCost
is set to 1 minute, the returned duration of the walking leg will be 15 minutesMultiplier arguments (e.g. preferences: {street: {walk: {reluctance: 3}}}
) are used to multiply costs of an leg
reluctance
is set to 3.0, the cost of each walking section will be multiplied by 3 and thus itineraries with less walking are preferred{
planConnection(
origin: {location: {coordinate: {latitude: 60.168992, longitude: 24.932366}}}
destination: {location: {coordinate: {latitude: 60.175294, longitude: 24.684855}}}
first: 2
) {
pageInfo {
endCursor
}
edges {
node {
start
end
legs {
duration
mode
distance
start {
scheduledTime
}
end {
scheduledTime
}
mode
duration
realtimeState
}
emissionsPerPerson {
co2
}
}
}
}
}
It is possible to define a searchWindow
in the requests to ensure that itineraries are searched from a specified search window time.
However, usually specifying a search window in the request doesn't make sense as it can be inefficient. If one isn't specified, a search
window is computed during the request which in many cases yields results. If one wants to specify a search window, it should preferable be
between 30 minutes and 8 hours (depends on how dense the transit network is in the area), and it should be used together with pagination.
The planConnection
query follows the Relay Graphql Cursor Connection specification. Only
difference is that there are no cursors available for the itineraries in the middle of a response (a hard-coded place holder string
is returned instead).
Pagination is highly recommended as usually it's possible to get enough itineraries without specifying a relatively high searchWindow
in the
request. Higher searchWindow
will mean that fetching the itineraries will take more time and in most cases, more itineraries will be found
than what is necessary.
The first
argument in the GraphQL query specifies the number of itinerary plans to be returned. To retrieve more results, you can use the after
argument with the value of endCursor
from the previous query's response's pageInfo
.
{
planConnection(
origin: {location: {coordinate: {latitude: 60.168992, longitude: 24.932366}}}
destination: {location: {coordinate: {latitude: 60.175294, longitude: 24.684855}}}
first: 2
after: <endCursor from previous query>
)....
Alternatively, if you want to fetch previous itineraries, before
and last
arguments can be used.
{
planConnection(
origin: {location: {coordinate: {latitude: 60.168992, longitude: 24.932366}}}
destination: {location: {coordinate: {latitude: 60.175294, longitude: 24.684855}}}
last: 2
before: <startCursor from previous query>
)....
Note: Pagination back-and-forth is not recommended. The previously returned itineraries should be stored in the client.
Note: If it's likely that you need to fetch for more itineraries, it's more efficient to just fetch more itineraries in the first
request instead of limiting it with the first
or last
as it's likely that the backend will have a lot more itineraries available to be returned.
label
. The label is then returned with the location
in the itineraries.{
planConnection(
origin: {location: {coordinate: {latitude: 60.168992, longitude: 24.932366}}, label: "Kamppi, Helsinki"}
destination: {location: {coordinate: {latitude: 60.175294, longitude: 24.684855}}, label: "Pisa, Espoo"}
first: 2
) {
pageInfo {
endCursor
}
edges {
node {
start
end
legs {
from {
name
}
to {
name
}
start {
scheduledTime
}
end {
scheduledTime
}
mode
duration
realtimeState
}
emissionsPerPerson {
co2
}
}
}
}
}
WALK
is used for direct street suggestions,
access, egress and transfers.{
planConnection(
origin: {location: {coordinate: {latitude: 60.199196699999995, longitude: 24.9397302}}}
destination: {location: {coordinate: {latitude: 60.168438, longitude: 24.929283}}}
first: 2
modes: {transit: {transit: [{mode: RAIL}]}}
) {
pageInfo {
endCursor
}
edges {
node {
start
end
legs {
from {
name
}
to {
name
}
start {
scheduledTime
}
end {
scheduledTime
}
mode
duration
realtimeState
}
emissionsPerPerson {
co2
}
}
}
}
}
fist: 5
)modes: {transit: {transit: [{mode: BUS}, {mode: RAIL}, {mode: TRAM}, {mode: FERRY}]}}
)preferences: {street: {walk: {speed: 1.7}}}
)Use a 10 minute safety margin for transfers (preferences: {street: { transit: {transfer: {slack: "10m"}}}
)
Use a 5 minute boarding cost (preferences: {street: {walk: {boardCost: 300}}}
)
boardCost: 300
is used and there is a 48min itinerary with one boarding and a 45min itinerary with two boardings, the 48 minute itinerary is returned, because its total cost is smaller (48min + 5min vs. 45min + 5min + 5min)Use multiplier of 2.1 for walk reluctance to prefer routes with less walking (preferences: {street: {walk: {reluctance: 2.1}}}
)
Specific departure date and time
dateTime: {earliestDeparture: "2024-06-13T14:30+03:00"}
In ISO-8601-formatted datetime with offset, e.g. 2024-06-13T14:30+03:00 for 2:30pm on June 13th 2024 at Helsinki's offset from UTC.{
planConnection(
origin: {location: {coordinate: {latitude: 60.179267, longitude: 24.951501}}, label: "Hakaniemi, Helsinki"}
destination: {location: {coordinate: {latitude: 60.1762, longitude: 24.836584}}, label: "Keilaniemi, Espoo"}
first: 5
dateTime: {earliestDeparture: "2024-06-13T14:30+03:00"}
modes: {transit: {transit: [{mode: BUS}, {mode: RAIL}, {mode: TRAM}, {mode: FERRY}]}}
preferences: {street: {walk: {speed: 1.7, reluctance: 2.1, boardCost: 300}}, transit: {transfer: {slack: "10M"}}}
) {
pageInfo {
endCursor
}
edges {
node {
walkDistance
duration
legs {
from {
lat
lon
name
stop {
code
name
}
}
to {
lat
lon
name
stop {
code
name
}
}
trip {
tripHeadsign
routeShortName
}
distance
legGeometry {
length
points
}
}
}
}
}
}
earliestDeparture
arguments.{
planConnection(
origin: {location: {coordinate: {latitude: 60.168992, longitude: 24.932366}}, label: "Kamppi, Helsinki"}
destination: {location: {coordinate: {latitude: 60.175294, longitude: 24.684855}}, label: "Pisa, Espoo"}
first: 1
) {
pageInfo {
endCursor
}
edges {
node {
start
end
legs {
nextLegs(numberOfLegs: 3) {
start {
scheduledTime
}
}
from {
name
}
to {
name
}
start {
scheduledTime
}
end {
scheduledTime
}
mode
duration
}
}
}
}
}
{
planConnection(
origin: {location: {coordinate: {latitude: 60.199196699999995, longitude: 24.9397302}}}
destination: {location: {coordinate: {latitude: 60.168438, longitude: 24.929283}}}
first: 2
) {
pageInfo {
endCursor
}
edges {
node {
start
end
legs {
fareProducts {
product {
id
name
... on DefaultFareProduct {
price {
amount
}
}
}
}
from {
name
}
to {
name
}
start {
scheduledTime
}
end {
scheduledTime
}
}
}
}
}
}