Routes
Routes draw curved A→B lines that follow the great circle — the shortest path on a sphere. Use them for trade flows, supply chains, migration corridors, or any map that needs to show a connection between two places. Endpoints can be ISO country codes (resolved to centroids) or explicit lat,lon coordinates.
Examples
Three routes with mixed styles:
https://api.maproll.io/map.svg?scope=world&theme=dark&routes=DE%3EBR:%2360a5fa:2:dashed:arrow%3BRO%3EAU:%23ec4899:2%3BJP%3EIN
Hub-and-spoke: six routes radiating from the US:
https://api.maproll.io/map.svg?scope=world&theme=light&routes=US%3EGB:arrow%3BUS%3EFR:arrow%3BUS%3EDE:arrow%3BUS%3EJP:arrow%3BUS%3EAU:arrow%3BUS%3EBR:arrow
Literal lat/lon endpoints — useful when the destination is a city, not a country centroid:
https://api.maproll.io/map.svg?scope=world&theme=dark&routes=44.43,26.10%3E52.52,13.40:%23ff8c00:3:arrow
Routes with marker icons at each endpoint:
https://api.maproll.io/map.svg?scope=world&theme=dark&routes=DE%3EBR:arrow%3BUS%3ECN:dashed:arrow&markers=52.52,13.40:airport:Berlin%3B-23.55,-46.63:pin:S%C3%A3o+Paulo:bottom%3B38.90,-77.04:flag:Washington%3B39.90,116.40:star:Beijing:right
Parameters
| Param | Type | Default | Allowed | Notes |
|---|---|---|---|---|
routes | string | — | See URL syntax | Semicolon-separated route definitions |
color | string | theme text color | 6-digit hex #rrggbb | Must start with # |
width | number | 2 | 1–20 (px) | Integer stroke width |
style | string | solid | solid, dashed | |
arrow | flag | off | arrow (presence) | Terminal arrowhead at the destination |
sea | flag | off | sea (presence) | Thread sea lanes instead of a great circle. See Sea routes |
URL syntax
routes=from>to[:options];from>to[:options];...
Options after the >to endpoint are type-distinguished — specify them in any order:
| Option | Detected by | Example |
|---|---|---|
| Color | Starts with # | #ff0000 |
| Width | All digits, 1–20 | 3 |
| Style | Literal solid or dashed | dashed |
| Arrow | Literal arrow | arrow |
| Sea mode | Literal sea | sea |
Endpoints are either:
- ISO codes — case-insensitive, resolved to the country's geographic centroid. Example:
DE,US,RO-B(subnational). lat,lonliterals — a comma in the token signals a coordinate. Example:44.43,26.10. Mix ISO and coordinates freely:DE>44.43,26.10.
The > separator was chosen over - so subnational ISO codes like RO-AG or US-CA remain unambiguous.
URL-encode > as %3E, # as %23, and ; as %3B in query strings.
# Simple ISO pair
routes=RO%3EDE
# With color and width
routes=RO%3EDE:%23ff0000:3
# Dashed with arrow
routes=RO%3EDE:dashed:arrow
# Lat/lon literal endpoints
routes=44.43,26.10%3E52.52,13.40
# Multiple routes
routes=DE%3EBR:dashed%3BUS%3ECN:arrow
JSON body syntax
Use POST /render/map with routes: RouteInput[]. The fromLatLon/toLatLon fields accept [lat, lon] and override the ISO lookup:
{
"scope": "world",
"theme": "dark",
"routes": [
{ "from": "RO", "to": "DE", "color": "#ff0000", "width": 3, "arrow": true },
{ "from": "US", "to": "CN", "style": "dashed" },
{ "from": "XX", "to": "YY", "fromLatLon": [44.43, 26.10], "toLatLon": [52.52, 13.40] }
]
}
Sea routes
Great circles draw the shortest path on a sphere, which is correct for flow visualization and ~accurate for flight paths. For ships it's wrong: a great circle from Shanghai to Rotterdam draws over Siberia. Adding the sea token threads the Eurostat marnet — through Suez, Panama, Malacca, etc.
https://api.maproll.io/map.svg?scope=world&theme=dark&width=1400&routes=31.23,121.47%3E51.92,4.48:sea:%230066cc:3:arrow
Transpacific routes split cleanly at the antimeridian, same as great circles:
https://api.maproll.io/map.svg?scope=world&theme=dark&width=1400&routes=35.44,139.64%3E33.77,-118.20:sea:%23f5b25c:3
You can mix sea and great-circle routes on the same map — the sea routes get their polyline, the rest stay great circles:
https://api.maproll.io/map.svg?scope=world&theme=dark&width=1400&routes=CN%3ENL:sea:%230066cc:3:arrow%3BUS%3ECN:%23f59e0b:2:arrow
In JSON body, set mode: "sea" on the route object:
{
"scope": "world",
"theme": "dark",
"routes": [
{
"from": "Shanghai",
"to": "Rotterdam",
"fromLatLon": [31.23, 121.47],
"toLatLon": [51.92, 4.48],
"mode": "sea",
"color": "#0066cc"
}
]
}
Sea route notes
- Snap to nearest port. Endpoints are snapped to the nearest vertex of the marnet. ISO centroids work for most countries (Switzerland snaps to Marseille via the Riviera, Germany snaps to Hamburg or Rotterdam, etc.), but the snapped port may not be the intended one. For specific ports, pass
lat,lonliterals. - Snap radius is 500 km. Endpoints further from any sea lane than that are rejected — the route lands in
X-Geo-Warnings: unknown-routes:sea:A>Band the render returns 200 with no line drawn. This catches truly landlocked pairs (Mongolia, Kazakhstan, Bolivia interior) rather than silently snapping to a faraway coast. - First-call latency. The maritime graph builds on the first sea-route request in a given server process (~100–500 ms). Subsequent calls reuse it. Cache-warm renders are fast.
- Cache key includes
mode. Sea and great-circle versions of the same endpoints are independent cache entries. - Restrictions, vessel draft, ETA — not yet exposed. The underlying library supports forcing routes to avoid specific canals (e.g. Suez disruption), gating canals by ship draft, and computing voyage duration. These will land later when there is demand.
Notes
- Great-circle curves. Routes are interpolated with 64 samples via
d3.geoInterpolate, giving a smooth arc at world scale. - Antimeridian split. When a great circle crosses the ±180° meridian (the date line), the renderer automatically splits it into two segments meeting at the map edges. No client-side handling needed.
- Routes draw below markers. Marker icons sit on top of route endpoints, so the line tip doesn't poke through the icon.
- Unknown ISO codes. If an endpoint can't be resolved to a feature in the current scope, the route is skipped and the pair is reported in the
X-Geo-Warnings: unknown-routes:A>Bresponse header. The render still returns 200. - Centroid vs. city position.
from=DEresolves to Germany's geographic centroid (central Germany), not Berlin. For routes that must connect city markers, pass explicitlat,lonliterals matching the marker's coordinates. - Limit: 500 routes per render. Exceeding this returns
400 invalid_routes. - No multi-stop routes. Workaround: pass
A>BandB>Cas separate routes. - Arrow markers are deduped by
(color, width). Twenty routes sharing a color and width share one SVG<marker>definition.
Related
- Markers — place icons at route endpoints
- Annotations — add hover text to regions along the route
GET /map.{svg,png}— full query parameter reference- POST /render/map — JSON body schema
- Supply-chain recipe — routes + markers + annotations together