Documentation menu
View links: agent answers on a map
A view link is a plan carried in a URL. An agent that plans a route, a day of stops or a whole fleet hands back one link instead of a table; whoever opens it sees the stops on a map at once, with each route redrawn by MapMap routing.
https://mapmap.ai/view?p=<payload>
No key, no account and no SDK are needed to open one, and nothing is stored on our side: the link carries its whole plan. Open /view without a payload for the short version of this page.
How an agent gets one
From the MCP server. The MCP server tools that answer with a
plan, route, plan_day and optimise_routes, are gaining a view_url field
that holds a ready-made link, and a view_url_note in its place when a plan is
too big to link. Pass the link on as the last line of the answer. Until that
field ships, build the link yourself as below.
Built by hand. The payload is base64url (RFC 4648 section 5, no padding) of compact JSON in UTF-8:
{"v":1,"kind":"route","costing":"auto","routes":[{"stops":[
{"lat":51.5309,"lon":-0.1233,"name":"Kings Cross"},
{"lat":51.5033,"lon":-0.1196,"name":"London Eye"}]}]}
P=$(printf '%s' "$JSON" | base64 | tr '+/' '-_' | tr -d '=\n')
echo "https://mapmap.ai/view?p=$P"
What it carries
| Field | Rule |
|---|---|
v | 1. |
kind | route (one route, the stops are its waypoints), plan (one route in visit order; a return to the start repeats the start as the last stop) or fleet (one route per vehicle). |
costing | auto, truck, bicycle, pedestrian or motor_scooter. Absent draws as auto. |
truck | With costing: "truck" only: height_m, width_m, length_m, weight_t, hazmat, tunnel_code (an ADR 8.6.4 code such as C or B/D). The redraw applies them, so a truck link is redrawn as that truck. |
depart_at | ISO 8601 with an offset, shown as written. |
title | At most 60 characters. |
routes | route and plan: exactly 1. fleet: 1 to 6. Each has an optional label (at most 24 characters), 2 to 22 stops, and optional totals. |
stops[] | lat, lon (required); name (at most 40 characters), arrive (HH:MM, 24-hour local clock) and dwell_min (whole minutes) optional. |
totals | distance_m and duration_s as the agent planned them, for the whole plan or (on a route) for that vehicle. duration_s is travel time; dwell is not included. |
Unknown fields are ignored, so a newer link still opens on an older page. A link that breaks a structural rule (the version, the kind, the number of routes or stops, a coordinate) does not open; an optional field that breaks its rule is left out, and a string over its limit is cut to it.
What it does not carry: no key, no email, no account, nothing about who made it. The stop coordinates and names, the title and the route labels are the whole of it, and anyone holding the link can read them. The query string is logged by the web host like any URL, so treat a view link as you would the stop list itself.
What the page shows
- The stops at once, numbered per route, in each route's colour.
- Each route redrawn now with MapMap routing for the declared vehicle, and its distance and time as redrawn now.
- The agent's own totals as as planned, beside the redrawn figures and never in place of them. Routing is time-aware, so a redraw can differ from the moment the plan was made.
- The stop list with arrival clocks and dwell times when the link has them.
- A plain message when a route has no path for that vehicle, when the redraw is unavailable, or when the link cannot be read.
The 6,000 character cap
The whole URL is at most 6,000 characters. A plan over the cap is trimmed in this order, stopping as soon as it fits:
- arrival clocks are dropped,
- then dwell times,
- then names are shortened to 20 characters,
- then names are dropped.
A plan still over the cap gets no link; from the MCP server, view_url_note
says so instead. A six-vehicle fleet of 22 stops each fits once its names are
dropped.
Writing an encoder
Any link that follows the rules above opens. If you want your links to match MapMap's byte for byte (useful for caching and tests), encode canonically:
- Keys in this order:
v,kind,costing,truck(height_m,width_m,length_m,weight_t,hazmat,tunnel_code),depart_at,title,routes(label,stops,totals),totals. A stop islat,lon,name,arrive,dwell_min; totals aredistance_m,duration_s. Leave absent fields out rather than writingnull. - Compact JSON, no whitespace outside strings; non-ASCII stays as UTF-8 and
/is not escaped. - Numbers as the shortest decimal that round-trips, integers without a fraction
(
4, not4.0), never an exponent, never-0. - Coordinates rounded to 5 decimal places, half away from zero;
totalsanddwell_minrounded to whole numbers. - Strings trimmed of surrounding whitespace; lengths count Unicode code points.
This plan:
{
"v": 1,
"kind": "plan",
"costing": "truck",
"truck": { "height_m": 4, "width_m": 2.55, "length_m": 16.5, "weight_t": 40, "hazmat": true, "tunnel_code": "C" },
"depart_at": "2026-10-20T08:00:00+01:00",
"title": "Brighton delivery round",
"routes": [
{
"label": "Van 1",
"stops": [
{ "lat": 50.8289, "lon": -0.1411, "name": "Brighton station", "arrive": "08:00" },
{ "lat": 50.8277, "lon": -0.1697, "name": "Hove Town Hall", "arrive": "08:09", "dwell_min": 10 },
{ "lat": 50.8397, "lon": -0.1466, "name": "Preston Park Rotunda Café", "arrive": "08:29", "dwell_min": 15 }
]
}
],
"totals": { "distance_m": 6881, "duration_s": 1122 }
}
encodes to exactly this link (open it):
https://mapmap.ai/view?p=eyJ2IjoxLCJraW5kIjoicGxhbiIsImNvc3RpbmciOiJ0cnVjayIsInRydWNrIjp7ImhlaWdodF9tIjo0LCJ3aWR0aF9tIjoyLjU1LCJsZW5ndGhfbSI6MTYuNSwid2VpZ2h0X3QiOjQwLCJoYXptYXQiOnRydWUsInR1bm5lbF9jb2RlIjoiQyJ9LCJkZXBhcnRfYXQiOiIyMDI2LTEwLTIwVDA4OjAwOjAwKzAxOjAwIiwidGl0bGUiOiJCcmlnaHRvbiBkZWxpdmVyeSByb3VuZCIsInJvdXRlcyI6W3sibGFiZWwiOiJWYW4gMSIsInN0b3BzIjpbeyJsYXQiOjUwLjgyODksImxvbiI6LTAuMTQxMSwibmFtZSI6IkJyaWdodG9uIHN0YXRpb24iLCJhcnJpdmUiOiIwODowMCJ9LHsibGF0Ijo1MC44Mjc3LCJsb24iOi0wLjE2OTcsIm5hbWUiOiJIb3ZlIFRvd24gSGFsbCIsImFycml2ZSI6IjA4OjA5IiwiZHdlbGxfbWluIjoxMH0seyJsYXQiOjUwLjgzOTcsImxvbiI6LTAuMTQ2NiwibmFtZSI6IlByZXN0b24gUGFyayBSb3R1bmRhIENhZsOpIiwiYXJyaXZlIjoiMDg6MjkiLCJkd2VsbF9taW4iOjE1fV19XSwidG90YWxzIjp7ImRpc3RhbmNlX20iOjY4ODEsImR1cmF0aW9uX3MiOjExMjJ9fQ