Get started
Data API

Routing

Routing

The routing queries: directions between waypoints, suggestions shaped to a target distance, isochrones for reachable area, and matrix for travel-time and distance grids. Every routing query takes an activity that selects a routing profile tuned to its terrain and movement style.

ActivityAPI valueWire formDirections
Hiking and trail runningHIKING_AND_TRAILhikingandtrailYes
Professional trailPROFESSIONAL_TRAILprofessionaltrailYes, off-network
RunningRUNNINGrunningYes
Backcountry skiingBACKCOUNTRY_SKIINGbackcountryskiingFreehand line only
Ski touringSKI_TOURINGskitouringYes, off-network
Cross-country skiingCROSS_COUNTRY_SKIINGcrosscountryskiingYes
Snowshoe walkingSNOWSHOE_WALKINGsnowshoewalkingYes
Gravel bikingGRAVEL_BIKEgravelbikeNot yet available
Mountain bikingMOUNTAIN_BIKEmountainbikeNot yet available
Road cyclingROAD_CYCLINGroadcyclingNot yet available

Each activity routes on a profile tuned to its terrain and movement style. Directions availability varies: most activities support turn-by-turn routing, backcountry skiing is freehand-line only, and cycling activities are not yet available for routing. The GraphQL ActivitySlug enum uses the uppercase value; the Map Studio and Tile APIs use the lowercase, underscore-free wire form.

All coordinates are [longitude, latitude] in WGS 84. Distances are in meters, durations in seconds, elevations in meters above sea level, and gradients in degrees.

How activities route

Each activity selects a routing profile tuned to its terrain, together with a preference and a waypoint snapping tolerance:

  • Preference. Most activities use balanced routing that favors pleasant, terrain-appropriate ways. Running and road cycling favor the fastest way. Professional trail takes the most-direct line, with no scenic bias.
  • Waypoint snapping. A waypoint must lie within a snapping distance of a routable way, or the query is rejected. Most activities use the standard ~400 m tolerance; snowshoe walking relaxes it to a few kilometers for off-trail points; ski touring and professional trail remove the limit entirely, snapping each waypoint to the nearest way at any distance, so routes can start or end far off-network.
  • Default speed. Each activity has a default speed used to estimate duration (for example ~4.5 km/h hiking, ~8 km/h professional trail, ~25 km/h road cycling). Override it per request with speed.

Backcountry skiing is freehand-only: it has no routing profile, so directions, suggestions, isochrones, and matrix are not available for it. Cycling activities (gravel, mountain, road) are not yet available for routing.

directions

Compute a route between an ordered list of waypoints for a given activity. Returns one or more routes with distance, duration, elevation, geometry, and a surface and way type analysis.

Input

directions(input: DirectionsInput!)

activity

ActivitySlug!

required

Activity to use for routing. Selects the routing profile and default speed.

waypoints

[[Float!]!]!

required

Ordered list of waypoints as [longitude, latitude] pairs. At least two are required, and at most 45 are accepted.

speed

Float

Travel speed in km/h. Overrides the activity's default speed and adjusts the estimated duration.

avoid

[RouteHazard!]

Hazards to route around: TOLLWAY, RESTRICTED_ACCESS, or both. Omitted or empty routes normally. Naming a hazard costs a second routing pass only when the first route actually crosses one. Avoidance is best-effort — read avoidance on each route to learn whether it was applied.

Example

query Directions($input: DirectionsInput!) {
  directions(input: $input) {
    routes {
      distance
      duration
      summary
      geometry
      elevation {
        ascent
        descent
        altitude {
          min
          max
        }
        gradient {
          min
          max
        }
      }
      analysis {
        surfaceInfo {
          fromIndex
          toIndex
          value
        }
      }
    }
  }
}

Response

DirectionsResult.routes is a list of DirectionsRoute. Each route carries:

distance

Float!

Total route distance in meters.

duration

Float!

Estimated route duration in seconds.

elevation

ElevationSummary!

Altitude bounds, total ascent and descent, and the gradient range in degrees.

geometry

GeoJSON!

Route path as a GeoJSON LineString. Coordinates are [longitude, latitude, altitude].

analysis

GeometryAnalysis!

Surface, way type, and slope segments along the route. Always present, but the segment lists are empty for activities that do not support analysis: only hiking and trail running, professional trail, and running populate them. See analysis.

avoidance

AvoidanceOutcome!

What the request's avoid list achieved. See hazards and avoidance below.

summary

String!

Human-readable one-line summary, for example 10.8 km, ~3h10m, +1138m / -579m elevation, 49% path, 30% road, 9% street.

Run this query live: open it in the playground and try it against the schema.

Hazards and avoidance

Some ways carry a toll, and some carry an access restriction — private, destination-only, customers, delivery, permit, or forbidden outright. Every routed result reports what it crosses on analysis.advisories:

tollway

Boolean!

The route crosses at least one way that charges a toll for this activity's mode of travel.

restrictedAccess

Boolean!

The route crosses at least one way carrying a genuine access restriction. Permissive ways — where the owner tolerates passage — do not raise this.

tollwayInfo

[TollwayInfo!]!

Where, as coordinate index ranges. Empty when the routing graph carries no toll data.

roadAccessInfo

[RoadAccessRestrictionInfo!]!

Where, as coordinate index ranges, each with the restrictions that apply. A way can carry several at once, so this one is a list per range.

suggestions never proposes a route through either. There is no avoid input and no opt-out: when no hazard-free candidate can be generated from the given points, the query fails with a validation error rather than returning one that crosses something. Proposing somewhere to go is a different act from a user deliberately routing across a private track.

directions can return one, because sometimes that is exactly what the user wants — a right of way they hold, a toll they will pay. It is the only query that does, so read advisories before you present the result. Pass avoid to route around them, and read avoidance to learn what happened:

avoidanceMeaning
NOT_REQUESTEDNo avoid list was given.
NOT_NEEDEDAvoidance was requested and the route crossed none of the named hazards.
APPLIEDThe route returned is the re-routed one. It may still cross a different hazard — check advisories.
NO_ROUTEThe hazards were excluded but no route survived, so the route returned is the original one and still crosses them. Usually a waypoint sits on the hazardous way, which no exclusion can route around.

suggestions

Generate route candidates that match a target distance for a given activity. Each candidate uses a different seed, producing a different route shape, so a client can offer the user several options ranked by proximity to the target.

No candidate crosses a tollway or an access-restricted way — see hazards and avoidance.

Input

suggestions(input: SuggestionsInput!)

activity

ActivitySlug!

required

Activity to use for routing.

start

[Float!]!

required

Starting point as [longitude, latitude].

distance

Float!

required

Target total distance for the route in meters, up to 200000. For a point-to-point route it must also be at least the straight-line distance between start and end.

candidates

Int!

required

Number of candidates to generate (1 to 10). Each uses a different random seed.

ascent

Float

Target elevation gain in meters. When set, candidates are also ranked by proximity to this value.

end

[Float!]

End point as [longitude, latitude]. Omit to loop back to start; provide a different point for a point-to-point route shaped to the target distance.

points

Int

default: 5

Number of shaping points (2 to 10). Higher values produce rounder loops. Only applies to loop routes.

speed

Float

Travel speed in km/h, overriding the activity default.

seeds

SuggestionSeeds

Pin specific seeds into the result (include) and avoid others in the fresh candidate pool (exclude). Useful to reproduce or vary previously returned routes. A seed in both lists is a validation error.

Example

query Suggestions($input: SuggestionsInput!) {
  suggestions(input: $input) {
    routes {
      distance
      duration
      summary
      seed
      elevation {
        ascent
        descent
      }
      geometry
    }
  }
}

Response

SuggestionsResult.routes is a list of SuggestionRoute, sorted by proximity to the target distance. Each carries the same distance, duration, elevation, geometry, analysis, and summary as a directions route, plus:

seed

Int!

The seed used to generate this candidate. Pass it back in seeds.include to reproduce the route or seeds.exclude to filter it out of fresh candidates. Reproducing a route also requires the same start, end, distance, and points.

isochrones

Compute reachability polygons from one or more origins for a given activity. Each range value yields one isochrone, so several ranges produce concentric polygons.

Input

isochrones(input: IsochronesInput!)

activity

ActivitySlug!

required

Activity to use for routing.

locations

[[Float!]!]!

required

Origin points as [longitude, latitude] pairs.

range

[Float!]!

required

Range values, in seconds for TIME or meters for DISTANCE. Multiple values produce concentric isochrones.

rangeType

IsochronesRangeType!

required

Whether range is expressed in TIME (seconds) or DISTANCE (meters).

Example

query Isochrones($input: IsochronesInput!) {
  isochrones(input: $input) {
    isochrones {
      value
      area
      reachFactor
      center
      geometry
    }
  }
}

Response

IsochronesResult.isochrones is a list of Isochrone, one per range value:

value

Float!

Range value in seconds or meters, matching the input range type.

area

Float

Area of the polygon in square meters.

reachFactor

Float

Ratio of the isochrone area to the theoretical area (0 to 1).

center

[Float!]

Center point as [longitude, latitude]. Null when the routing provider reports no center for this isochrone: the value is forwarded verbatim from the provider, never reconstructed from the input location.

geometry

GeoJSON!

Polygon geometry of the isochrone.

matrix

Compute a grid of travel durations and/or distances between locations for a given activity. Limit the grid to specific origins or destinations with the sources and destinations index lists.

Input

matrix(input: MatrixInput!)

activity

ActivitySlug!

required

Activity to use for routing.

locations

[[Float!]!]!

required

Locations as [longitude, latitude] pairs.

metrics

[MatrixMetric!]!

required

Metrics to compute. At least one of DISTANCE (meters) or DURATION (seconds).

sources

[Int!]

Indices of locations to use as sources. When omitted, all locations are used.

destinations

[Int!]

Indices of locations to use as destinations. When omitted, all locations are used.

Example

query Matrix($input: MatrixInput!) {
  matrix(input: $input) {
    durations
    distances
  }
}

Response

MatrixResult carries a grid per requested metric. Each grid is a row-per-source array of values, with inner null entries marking unreachable pairs:

durations

[[Float]!]

Duration grid in seconds. Present only when the DURATION metric was requested.

distances

[[Float]!]

Distance grid in meters. Present only when the DISTANCE metric was requested.

Next steps