V3 is in beta. General availability (GA) is planned for January 2027.
This page describes the V3 API (
/v3/routing). For the V2 API (/v2/vrp), see the V2 version of this page.straight_line engine, computes them from the distance as the crow flies. This page covers what you control about that lookup and what you can observe in the response.
What goes into the matrix
Every coordinate the request can route to becomes a matrix location:- each job’s
location - each shipment’s
pickup.locationanddelivery.location - each shift’s
startandend, whether given inline or as adepots[].id - each depot a shift lists in
reloads
[longitude, latitude] everywhere in the API.
Travel is looked up in both directions, and the two need not match: one-way streets and turn restrictions can make A to B longer than B to A. The solver uses each direction as returned.
Fields that control travel data
Four request fields decide which travel data a solve uses.string
Which data prices travel. One of
tomtom, osm, tomtom_real_time, straight_line. Omitted, it follows departure_time: osm without one, tomtom with one. See Choosing an engine.string (RFC 3339)
The instant the traffic lookup is made for. Any UTC offset is accepted. Omit it, and
engine too, and travel times are free-flow: the same request is priced the same at any time of day. Set it to plan tomorrow’s 08:00 routes against morning-rush travel times, or to re-run a past day under its original conditions; the engine is then tomtom unless you name another. Only valid with the tomtom engine.number
default:"50"
The speed every leg is driven at with the
straight_line engine, from 1 to 1000 km/h. Sending it with any other engine, or with no engine, is a 400 whose error item points at /problem/travel/speed_kmh. See Straight-line travel.string
default:"car"
The routing profile for this vehicle:
car, truck, or bike, in lowercase; any other value is a 400. Vehicles with different profiles each get their own matrix, so a mixed fleet is planned with the right travel times per vehicle type. The profile changes speeds only: truck carries no dimensions or restrictions, so it does not avoid a low bridge or a weight-limited road.Choosing an engine
Omitted, the engine follows
departure_time. Without one the plan is priced on free-flow osm times, so the same request is priced on the same travel times at any hour. With one it is priced on tomtom typical traffic at that instant, which is the setting for planning a known departure. Send engine: "tomtom" without a departure_time for typical traffic at the moment the request is processed; that moment moves with the clock, so a request sent at 08:30 plans a whole day on rush-hour speeds. Traffic-aware times run above free-flow: on a three-city Belgian sample, tomtom at the Monday 07:30 rush was 18 % slower than osm, and tomtom at 02:00 equal to it.
Sending departure_time together with osm, tomtom_real_time or straight_line is a 400 whose error item points at /problem/travel/departure_time: free-flow and straight-line travel have no traffic to look up, and live traffic is always “now”. See Errors for the error body.
Straight-line travel
straight_line skips the road network. Each leg’s distance is the great-circle distance between its two coordinates in whole metres, and its travel time is that distance at speed_kmh, rounded to the nearest second:
tomtom or osm: a straight line ignores roads, rivers and one-way streets.
- Travel is the same in both directions, has no traffic, and is computed without a lookup, so it never fails and never falls back to an estimate.
options.travel_fallbackhas no effect andsummary.travel_estimatedstays absent. - Every vehicle drives at
speed_kmh, so avehicles[].profileother thancaris a400pointing at that vehicle’sprofile. To make one vehicle faster or slower, use itsspeed_factor. - There is no road to draw, so
options.polylineis a400pointing at/options/polyline, and stops carry nosnapped_location.
Adjusting travel and service time per vehicle
The matrix is the same for every vehicle on a profile. Two vehicle fields scale time on top of it:number
default:"1.0"
Travel-speed multiplier, in
[0.001, 5]. Effective travel time is the matrix time divided by speed_factor, so 1.2 models a faster vehicle and 0.8 a slower one. It affects driving only.number
default:"1.0"
Work-rate multiplier for time spent at stops, in
[0.001, 5]. Effective service time is service_duration_s / service_factor, so values above 1.0 model a crew that works faster. It does not change setup_duration_s, depot handling time, waiting, or breaks. A shift can override it with its own service_factor.What the matrix drives
The same travel times and distances feed every part of the plan:- Feasibility. Time windows, shift hours, and the route limits
vehicles[].limits.max_distance_mandvehicles[].limits.max_route_duration_sare all checked against them. - Cost.
objective.costs.per_travel_kmis charged on route distance, andobjective.costs.per_route_houron each route’s start-to-finish span, which includes the driving time between stops. - The reported figures.
routes[].distance_m,routes[].time.travel_s, and each stop’stravel_sanddistance_mcome from the matrix, with the vehicle’sspeed_factorapplied to the times.
What you see in the response
[number, number]
The stop’s coordinate moved to the nearest point on the road network, as
[longitude, latitude]. Present when the routing engine could snap the point. A large gap between location and snapped_location means the coordinate you sent is not near a road; a common cause is swapped longitude and latitude.string
unreachable when the road network has no connection to or from a job’s location, for example a point on an island with no road link. The solver never routes over a missing connection, so the job comes back unassigned instead. This is a fact about the input, so more solve time will not place it; fix the coordinate.string
The road geometry of the route, as an encoded polyline at precision 5. Returned only when you set
options.polyline to simplified or full. It is traced with the vehicle’s profile, so it follows the same roads the plan was costed on. The lookup is best-effort: if it fails, the plan is returned without polyline.Latency and failures
The travel lookup happens before the search and is not counted againstoptions.time_limit_s. Total response time is the lookup plus the search, so the more distinct locations a request has, the longer the lookup takes: the matrix grows with the square of the location count.
- Travel data can be reused between requests, under three conditions. The request uses the
osmengine (the default without adeparture_time) or thetomtomengine, sets nodeparture_time, and has at most 200 distinct locations. Each engine’s travel data is reused only for that engine. Location pairs looked up within the last hour can then be served without a new lookup, which suits dispatch workflows that re-solve the same routes as jobs arrive. Reuse is not guaranteed, so do not size a client timeout on it. - A
straight_linerequest does no lookup at all, so its travel takes no noticeable time and cannot fail. - Every other request does a fresh lookup. That covers an explicit
departure_time, thetomtom_real_timeengine, and any request with more than 200 distinct locations. Setdeparture_timewhen you are planning for a specific future or past instant, not on every call in a re-solve loop. - All coordinates in one request must lie in the same region. A request whose coordinates span more than one region or continent is rejected with
400. When you get this error, check that every coordinate is in[longitude, latitude]order. - Any other failure to fetch travel times is answered with an estimate, whatever the cause: an outage, a timeout, overload or an error from the provider. Every pair is estimated from straight-line distance with a typical detour factor and speed for the vehicle
profile, on solve, evaluate and suggest alike. Solve and evaluate responses carrysummary.travel_estimated: true; a suggest response, which has nosummary, carries a top-leveltravel_estimated: true. An estimate knows nothing about one-way streets or traffic, is the same in both directions, and can be tens of percent off, so the plan, time-window feasibility,score.violation_countand suggest’s insertions hold only against it. Noroutes[].polylineis returned, andsnapped_locationcan be missing from the stops. Send the request again once the provider is back if the result must hold on the road. - A solve or suggest with
options.travel_fallback: "fail"fails instead. It returns502and codetravel_provider_error; when the provider is temporarily unavailable you get503with aRetry-Afterheader. Both are safe to retry. Evaluate has no such option.
Related topics
Constraints
Time windows, route limits, and reachability, all checked against the travel matrix
Performance guide
How lookup time and search time add up to response time
Objective function
How distance and time become cost
Errors
The error body, status codes, and which failures to retry