Route Preferences
By default Directions returns the fastest route for the mode. The options on this page change that. You can lean away from tolls without banning them, cap the vehicle’s speed, say which way a vehicle faces at the start, pass a pickup point without stopping, or ask what the route you got would cost on foot.
Preferences and penalties change which route is chosen. They never change duration_s. The same goes for the turn costs motor vehicles pay by default for left turns across traffic and the like. That is always the travel time of the route you get back, so a 20-minute toll-free detour reports 20 minutes, not 20 minutes plus whatever penalty made it win. Speed options (top_speed, fixed_speed) are different: they change how fast you drive, so they change duration_s too.
All of these are top-level fields of the POST /route body. /matrix takes the costing options, /isochrone takes the two speed options, and PlazaQL takes all of them as keyword arguments with the same names, values and errors.
Preferences
Section titled “Preferences”Each preference is a number from 0 to 1. Leave it out, or send 0.5, and that kind of road is priced as usual. Below 0.5 its cost goes up, to the factor in the table at 0, so the router uses it only when the alternative is much worse. Above 0.5 its cost goes down, to 0.9x at 1, which tips close calls in its favour.
| Field | Roads | At 0 | Modes |
|---|---|---|---|
use_highways | Motorways and trunk roads, with their links | 10x | auto, truck, motorcycle, motor_scooter |
use_tolls | Ways tagged toll=yes | 10x | auto, truck, motorcycle, motor_scooter |
use_ferries | Ferry routes (route=ferry), see below | 10x | every mode |
use_living_streets | highway=living_street | 5x | every mode |
use_tracks | highway=track | 15x | foot, bicycle |
Ferries are part of the road network. A ferry takes as long as its OSM duration tag says; without one it sails at 20 km/h. Cars, trucks, motorcycles, walkers and cyclists all board unless the ferry’s tags keep them off (motor_vehicle=no on a foot ferry, say). use_ferries: 0 keeps you on land unless the drive round is ten times longer than the crossing. exclude: "ferry" rules ferries out completely.
Factors multiply. A tolled motorway with use_tolls: 0 and use_highways: 0 costs 100x its travel time.
An option a mode doesn’t take is a 422, so use_tolls with mode: "foot" fails instead of being ignored. Cars and trucks never drive tracks, which is why use_tracks is foot and bicycle only. Motorcycles have their own use_trails option instead, see Motorcycle and Scooter Routing. To keep off a road type completely, use exclude instead.
curl -X POST https://plaza.fyi/api/v1/route \ -H "x-api-key: pk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "origin": { "type": "Point", "coordinates": [-74.0060, 40.7128] }, "destination": { "type": "Point", "coordinates": [-73.9855, 40.7580] }, "use_tolls": 0, "use_highways": 0.3 }'Shortest distance
Section titled “Shortest distance”"shortest": true minimises distance instead of time. Travel time only breaks ties between equally long routes. duration_s is still the time it takes to drive the short route. Turn costs don’t apply. shortest can’t be combined with a preference or a penalty (422), because they would mix metres with seconds. It works for every mode.
| Field | Range | Modes | Effect |
|---|---|---|---|
top_speed | 10-252 km/h, whole numbers | auto, truck, motorcycle, motor_scooter | The vehicle never goes faster. Roads with a higher speed are driven at this speed. A motor scooter is capped at 45 km/h without it, and top_speed replaces that cap. |
fixed_speed | 1-252 km/h, whole numbers | auto, truck, motorcycle, motor_scooter | Every road is driven at exactly this speed. Road class, speed limits, surface, slope and the time of day are ignored; waits at junctions and signals still count. Wins over top_speed. |
Both change the route and its duration_s. Use top_speed for a vehicle that is slower than the traffic around it, such as a moped, a tractor or a bus with a governor. Use fixed_speed when you already know your average speed and want Plaza to only find the road.
Penalties
Section titled “Penalties”Penalties are seconds added to the cost of part of the route. Like preferences, they change the choice and not duration_s. Each takes 0 to 3600.
| Field | Added for | Modes |
|---|---|---|
maneuver_penalty | Each junction delay the route reaches: intersections, and traffic signals, stop signs or crossings where two roads meet. It counts junctions passed, not turns: going straight on through a crossing pays it too. A road without junctions pays nothing, however Plaza splits it. Higher values favour routes through fewer junctions and stops. Roads Plaza hasn’t modelled junctions for yet carry no penalty. | auto, truck, motorcycle, motor_scooter |
service_penalty | Each service road (highway=service) the route turns into from another kind of road: parking aisles, alleys, driveways. A service road crossed by other streets still pays once. | auto, truck, motorcycle, motor_scooter |
gate_cost | Each gate passed (barrier=gate, lift_gate, swing_gate, sliding_gate, hampshire_gate), unless the gate is tagged access=yes, permissive, designated or public. | every mode |
toll_booth_cost | Each toll booth (barrier=toll_booth) passed. The 15 s a booth stop takes is already in duration_s; this only makes booths less attractive. | auto, truck, motorcycle, motor_scooter |
country_crossing_cost | Each border crossed: a barrier=border_control node, or a road leaving one country for another. | every mode |
{ "origin": { "type": "Point", "coordinates": [2.3522, 48.8566] }, "destination": { "type": "Point", "coordinates": [2.2945, 48.8584] }, "maneuver_penalty": 20, "service_penalty": 60}Gates, bollards and closures
Section titled “Gates, bollards and closures”Some of this happens without any option. A bollard, block or chain across a road closes it to cars, trucks, motorcycles and scooters but not to walkers and cyclists. A stile, kissing gate, turnstile, log or debris lets only walkers through, and a wall, fence, rope or jersey barrier lets nobody through. A locked gate, or one tagged access=private or access=no, is closed to everyone its own tags don’t let through: foot=yes on a private gate still lets walkers past. A barrier where roads meet stops traffic passing it, not reaching it: with a bollard where a footway crosses a street, you can drive up to the bollard from either end of the street. A trip that starts at the bollard can leave it either way, on routes, matrices and isochrones alike, but it still can’t drive through. Roads under construction (highway=construction) are closed to every mode. A road tagged access=no is closed too, unless a more specific tag such as foot=yes or bicycle=yes opens it for that mode.
Closures that only hold at some times follow depart_at. Say a mountain pass is tagged access:conditional = no @ (Nov-Apr). It is closed to a route leaving in January and open to one leaving in July:
{ "origin": { "type": "Point", "coordinates": [8.5683, 46.5592] }, "destination": { "type": "Point", "coordinates": [8.4167, 46.5594] }, "mode": "auto", "depart_at": "2026-07-15T09:00:00+02:00"}Without depart_at the road keeps its plain value, which for that pass is open. maxspeed:conditional works the same way, and trucks also read conditional weight, height, width, length and axle-load limits.
Other gates stay open, but drivers pay 330 s of routing cost for each gate whose access isn’t tagged, so a route only goes through one when the way round is more than five and a half minutes slower. Walkers and cyclists don’t pay it. gate_cost adds to it, for every mode. As with every penalty, duration_s stays the real travel time.
Drivers (cars, trucks, motorcycles and scooters) also pay 300 s of routing cost to board a ferry from a road, and 15 s to turn onto a track from another kind of road. Valhalla adds the gate’s 30 s and the ferry’s 300 s to its arrival time. Plaza doesn’t: they only decide which route wins, and duration_s is the time on the road and the ferry’s sailing time. Matrices, isochrones and the other computations that price travel time alone leave all of them out.
Location types
Section titled “Location types”location_types has one entry per point: origin, each waypoint, destination.
| Type | Meaning |
|---|---|
break | A stop. The route is split into legs here and gets a waypoint step. This is the default, and the origin and destination must be break. |
through | Pass this point without stopping. No new leg, no arrival step, and no turning back here: for the rest of the way to the next point, the route can’t use the road segment it came in on at all. |
via | Like through, but turning back is allowed. Use it to pull a route past a point that sits at a dead end. |
curl -X POST https://plaza.fyi/api/v1/route \ -H "x-api-key: pk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "origin": { "type": "Point", "coordinates": [-74.0060, 40.7128] }, "destination": { "type": "Point", "coordinates": [-73.9855, 40.7580] }, "waypoints": [{ "type": "Point", "coordinates": [-73.9866, 40.7306] }], "location_types": ["break", "through", "break"], "steps": true }'With steps, this route has one leg and no waypoint step. waypoint_names still has one entry per point; names of through and via points are not used.
Heading and side of the road
Section titled “Heading and side of the road”These pick which way the vehicle travels at a point. Like location_types they have one entry per point, with null for points that don’t need one.
| Field | Values | Meaning |
|---|---|---|
headings | 0-360 | Direction of travel, degrees clockwise from north. |
heading_tolerances | 0-180, default 60 | How far the road may differ from the heading. Needs a heading at the same point. |
preferred_sides | same, opposite, either | same keeps the point on the vehicle’s driving side (the right, or the left in left-hand-traffic countries, Hong Kong and Macau included), so a passenger gets out at the curb. opposite puts it across the road. either is the default. |
approaches | curb, unrestricted | Mapbox’s name for the same thing. curb is preferred_sides: same; unrestricted is the default. Sending curb and opposite for the same point is a 422. |
With a heading or a side, the point snaps to the nearest road within 500 m that can be travelled that way, and the route goes past the point in that direction. It may not use that road the other way round, so a car facing east at the start drives east first, even if its destination is behind it. The exception is a dead end: facing into a cul-de-sac, the route turns round at its end rather than failing. When the origin and destination are on the same road, facing the same way with the destination ahead, the route is just that road. If no road nearby fits, or the one that fits is ruled out by exclude, avoid_datasets or a truck limit, the point snaps as if neither option were set. So does a point that lies exactly on the road with only preferred_sides set, since it has no side.
{ "origin": { "type": "Point", "coordinates": [-73.9925, 40.7505] }, "destination": { "type": "Point", "coordinates": [-73.9855, 40.7580] }, "headings": [90, null], "preferred_sides": [null, "same"]}Routes start and end at junctions. When the origin is in the first half of its road segment, the route includes that segment; in the second half, it starts at the next junction. The destination works the other way round. A waypoint’s segment is always included. Alternatives start and end at the junctions without the segment.
Recostings
Section titled “Recostings”recostings prices the route you got under up to five other costing models, without routing again. Each one has a name, an optional mode (auto, foot, bicycle, motorcycle or motor_scooter, defaulting to the route’s own mode; truck routes must name one) and any of the options above. A bicycle, walking or motorcycle recosting uses the request’s options for that mode when the route has them, else the defaults.
curl -X POST https://plaza.fyi/api/v1/route \ -H "x-api-key: pk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "origin": { "type": "Point", "coordinates": [-74.0060, 40.7128] }, "destination": { "type": "Point", "coordinates": [-73.9855, 40.7580] }, "recostings": [ { "name": "slow_van", "top_speed": 80 }, { "name": "no_tolls", "use_tolls": 0 }, { "name": "walk", "mode": "foot" } ] }'The route’s properties then include:
"recostings": { "slow_van": { "duration_s": 1320.4, "cost": 1320.4 }, "no_tolls": { "duration_s": 1104.9, "cost": 4870.2 }, "walk": { "duration_s": null, "cost": null }}duration_sis the travel time of the same path under that model: the same road, driven at that mode’s speeds, with the request’sdepart_at.costis what the router would have scored the path: seconds with preferences and penalties added, or metres withshortest. Likeduration_s, it leaves out waiting at the junction where the route ends. Comparingcostacross recostings shows how much a preference dislikes the route you took.- Both are
nullwhen that mode can’t use the path, for example walking on a motorway or cycling the wrong way down a one-way street.
Each entry can also be a string, "name: key=value, ...", which is the form PlazaQL uses: "no_tolls: use_tolls=0" or "walk: mode=foot". Waypoint routes sum the legs; alternatives each get their own.
Isochrones and matrices
Section titled “Isochrones and matrices”/matrix takes every costing option. Pairs follow the route the options and turn costs pick, and duration_s is its travel time.
/isochrone takes top_speed and fixed_speed. An isochrone’s budget is travel time, so preferences and penalties have nothing to change there and are a 422.
Errors
Section titled “Errors”Everything here is checked before routing. A bad value is a 422 validation_error naming the field:
- a number out of range:
use_tolls must be a number from 0 to 1 - an option the mode doesn’t take:
use_tolls applies to mode auto, truck, motorcycle or motor_scooter, not foot(the same fortoll_booth_cost) shortestwith a preference or penalty:shortest cannot be combined with use_tolls- a per-point list of the wrong length:
headings must have one entry per point (origin, waypoints, destination): expected 3, got 2 - a recosting without a name, with a repeated name or an unknown option
location_types,headings,heading_tolerances,preferred_sides,approachesorrecostingswithev- any of these options with
mode: "transit"
PlazaQL
Section titled “PlazaQL”route() takes all of these as keyword arguments, matrix() and ev_route() take the costing options, and isochrone() takes the speeds. PlazaQL has no null, so per-point options use the ;-separated string form when some points have no value, and recostings are strings:
route( origin: point(40.7128, -74.0060), destination: point(40.7580, -73.9855), waypoints: [point(40.7306, -73.9866)], use_tolls: 0, top_speed: 100, location_types: ["break", "through", "break"], headings: "90;;", preferred_sides: ";;same", recostings: ["walk: mode=foot"]);REST accepts the string forms too, so "headings": "90;;" and "headings": [90, null, null] mean the same thing.