Documentation menu
API endpoints
122 public endpoints, one page each. Every page on this index is generated at build time from the document the gateway publishes at /openapi.json, so what you read here is what that deployment declares, not a second copy of it maintained by hand.
gateway 0.3.0 · read from https://api.mapmap.ai/openapi.json on 2026-11-01 · 48 admin and console operations are not listed
The rules these endpoints share, authentication, coordinate order, quotas, the error model and the ADR tunnel codes, are defined once on API conventions. For the narrative version with worked requests, read the API reference guide.
assets
Static map assets: SDF font glyph ranges and sprite sheets referenced by compiled styles. Public, unmetered, immutable caching
`GET /avatars/{version}/{*path}`: one file of the vehicle-avatar asset set.
`GET /fonts/{fontstack}/{range}.pbf`: one SDF glyph range.
`GET /sprite/{file}`; a sprite-sheet file: `<sheet>.json`, `<sheet>.png`, `<sheet>@2x.json` or `<sheet>@2x.png` (the four names MapLibre resolves from a style's `sprite` base URL), for either sheet in [`SPRITE_STEMS`].
boundaries
Administrative boundaries. GET /boundary: the country and first sub-division at a point, from the Valhalla admins.sqlite (501 unless the operator sets SN_ADMIN_BOUNDARIES_DB). GET /v1/boundaries and GET /v1/boundaries/{id}: OSM admin_level 2 to 10 boundaries by name or point with a stable boundary_id, and one boundary's simplified polygon, for custom regions by boundary_id (501 unless the operator sets SN_BOUNDARIES_DIR). Standard price class, metered per request. OSM-derived (ODbL); see docs/THIRD-PARTY-NOTICES.md
clearance
Measured overhead clearance along a route, from baked survey geometry (crates/sn-clearance). A within-survey difference with a stated uncertainty bound, never a signed or legal clearance and never a pass over ground the survey did not cover. Standard price class, never premium: a safety check carries no extra charge. 501 unless the deployment publishes at least one clearance artefact
collection
compliance
Metered ADR compliance endpoints
coordinates
Reprojection between reference systems, and the published list of the ones it will do it for. Every supported CRS states its own datum-shift error, and a code outside the table is refused by name rather than approximated. Standard price class, one unit per request whatever it carries
directional
Directional place lookup: given a position AND a bearing, the places inside that cone, each with its distance, its own bearing, its angular offset from the query bearing, and a visibility verdict computed against the bare-earth elevation model and OpenStreetMap building footprints. Every verdict names what it was checked against and can answer `unknown`; a place that could not be checked is returned labelled rather than silently kept or dropped. A QUERY surface only: it takes a position and a bearing and answers, and nothing here is route-triggered or proactive. Standard price class, billed a flat block
elevation
Point and along-route elevation via Valhalla's native /height action. Honest per-sample source/resolution metadata and a null (never a guess) wherever the engine has no DEM tile coverage. Standard price class, metered per request. 501 unless the operator sets SN_ELEVATION_ENABLED=true (off by default until DEM tiles are staged)
feedback
Integration retros: the structured end-of-integration report an agent (or human) submits once: what was built, problems, gotchas, wins and docs gaps. Key-authenticated, never charged, rate-limited per key. Content is stored verbatim and treated as untrusted text
geocode
geocoding
Metered Photon geocoding proxy (forward and reverse): GeoJSON passthrough, Standard price class. 501 unless the operator sets SN_PHOTON_URL
`GET /geocode?q=<text>&limit=<n≤10>&lang=<code>&bias=<lon>,<lat>&bbox=<minLon>,<minLat>,<maxLon>,<maxLat>&country=<cc>[,<cc>…]`.
`POST /geocode/batch`: many geocodes in one call.
`GET /geocode/retrieve?id=<document id>`.
`GET /geocode/reverse?lon=<f64>&lat=<f64>[&kinds=..&categories=..&name=..&radius_m=..&limit=..]`.
`GET /geocode/suggest?q=<text>&limit=<n≤10>&bias=<lon>,<lat>&bbox=…&lang=…`.
live
Live Earth layers for display: earthquakes, volcano alerts and fire detections (USGS, NOAA NCEI, NASA FIRMS), NOAA GFS forecast frames processed by MapMap, and the NOAA SWPC aurora forecast and Kp. Freshness is a field on every answer, never an error. Forecast and reported data for display, never a warning service. Standard price class, one unit per request; a browser (maps) key may read them. 501 unless the operator sets SN_LIVE_DIR and SN_WEATHER_DIR.
`GET /v1/events`: earthquakes, US volcano alerts and satellite fire cells as GeoJSON, with each feed's freshness.
`GET /v1/space-weather`: the aurora forecast and Kp.
`GET /v1/space-weather/aurora.png`: the aurora probability grid.
`GET /v1/weather/frames`: the kept NOAA GFS forecast runs and their frame paths.
`GET /v1/weather/frames/gfs/{run}/{field}/{file}`: one frame file, verbatim.
map-issues
User map-error reports ("Report a map issue"): a pin, a category and an optional note, key-authenticated and metered at the Standard price class. Reports never edit map data directly. The team triages them (see the admin surface) and verified fixes flow into the deployment's OSM-overrides file and upstream OpenStreetMap contributions. The same path carries drivers' traffic reports (the traffic-* categories, which require heading_deg): they are deleted after 24 hours, never published, and reach other drivers only through POST /v1/incidents/along once two drivers agree
mapbox-compat
Shape-compatible aliases of MapMap endpoints for clients written against Mapbox: Directions, Matrix, Isochrone, Optimization v1 and Geocoding (v6 and legacy v5) paths, parameters and response shapes, each served by the MapMap endpoint it wraps and metered as that endpoint. `access_token` is accepted as the key on these paths. A Mapbox option MapMap cannot honour is refused with a 400 naming the supported set, never silently dropped. `driving-traffic` is served as `driving` (traffic-aware times cover the England strategic road network only). Geocoding answers are MapMap's own in Mapbox's shape, not Mapbox's results
Mapbox-compatible Matrix (see module docs).
Mapbox-compatible Directions (see module docs). Metered exactly as `GET /route/v1`: one unit per started block of 20 waypoints, premium on the `truck` profile.
Legacy Mapbox Geocoding v5 (`mapbox.places`), forward or, for a `lon,lat` query, reverse (see module docs). One standard unit.
Mapbox-compatible Isochrone (see module docs).
Mapbox-compatible Optimization v1 (see module docs). Billed as the optimise units plus one route unit.
Mapbox Geocoding v6 forward search (see module docs). One standard unit.
Mapbox Geocoding v6 reverse lookup (see module docs). One standard unit.
meta
Unauthenticated service metadata
Minimal service index.
Backend-aware health check: 200/`ok` when the primary routing backend answers, 503/`degraded` when it does not.
`llms.txt` (<https://llmstxt.org/>) describing the API for agent consumers, with runnable curl examples.
The generated OpenAPI 3.1 document, with the configured public URL as the server entry.
The read-only status surface: what this box is serving.
Terms of service: a 307 redirect to `SN_TERMS_URL` when the operator hosts the terms elsewhere (e.g. the website's `/terms` page), otherwise a plain-text pointer so the `tos` URL echoed by self-serve signup never dangles.
The minimum-version signal for one MapMap app. Keyless and unmetered.
The public provenance record: what this deployment runs.
oauth
OAuth 2.1 authorization server: RFC 8414 discovery, RFC 7591 dynamic client registration, and the token endpoint. Public clients only (PKCE S256, no client secrets), rotating refresh tokens with reuse-revokes-chain, and client-id metadata document (CIMD) clients. An issued `sno_` access token resolves in the auth layer to a real API key, so every existing quota, metering and billing rule applies unchanged. The interactive authorization page lives on the website (SN_OAUTH_AUTHORIZE_URL); 501 unless the deployment has one
RFC 8414 authorization-server metadata.
Mints an authorization code for a signed-in identity. **Internal**: admin-token gated, exactly like `/admin/*` and the website's other server-to-server calls, and never reachable from a browser.
Dynamic client registration (RFC 7591). Public clients only: the response carries no `client_secret`, and any `token_endpoint_auth_method` other than `"none"` is refused rather than silently downgraded.
The token endpoint: authorization-code and refresh-token grants.
places
Customer places ("bring your own places"): per-key proprietary place datasets with full-text and nearest search over the caller's own tantivy index. Never merged into OSM-derived data (ODbL boundary). All routes key-authenticated and metered at the Standard price class
`DELETE /places`: remove the caller's dataset and index. Idempotent: deleting an empty slate is still a 204.
`GET /places`: the caller's stored dataset.
`PUT /places`: replace the caller's place dataset and rebuild its search index.
`GET /places/nearest?lat=…&lon=…&limit=…`: the caller's places nearest to a point, by haversine distance (no text query, no index).
`GET /places/search?q=…&lat=…&lon=…&limit=…&category=…`: full-text search over the caller's own places, proximity-biased when a focus point is given.
pointclouds
routing
Metered routing endpoints
Finds the least-cost meeting point of several locations (see module docs).
Isochrone endpoint (see module docs).
Snaps each location to the road graph (see module docs).
Matrix endpoint (see module docs).
Route-optimisation endpoint (see module docs). `/optimize` is an alias.
Re-plan a fleet mid-shift (see module docs). `/optimize/replan` is an alias.
Valhalla-compatible route endpoint (see module docs).
Along-route search endpoint (see module docs).
Progress endpoint (see module docs).
Report endpoint (see module docs).
OSRM-compatible route endpoint (see module docs).
Map matching to per-edge attributes (see module docs).
Map matching to a route (see module docs).
Safety cameras along a route shape (see module docs).
Best EV chargers along a route (see module docs).
Capacity-constrained clustering (see module docs).
Plans a chain of errands against a hard arrival time.
Plans an EV journey with its charge stops (see module docs).
Cheapest fuel along a route (see module docs).
Traffic incidents and closures along a route shape (see module docs).
Submit a drive-every-street coverage plan to the asynchronous lane.
Submit a matrix to the asynchronous lane.
Submit an optimisation problem to the asynchronous lane.
Submit a mid-shift re-plan to the asynchronous lane.
`POST /v1/route/heritage` (see module docs).
`POST /v1/route/observations` (see module docs).
Forecast weather along a route, aligned to each point's ETA (see module docs).
The curated UK zone dataset, with provenance.
self-serve
Agent-first self-serve keys: one-call signup, magic-link verification, quota-free status poll. Beyond the free tier, 402 responses use the x402 machine-payment wire format
List the caller's recent jobs (quota-free).
Read one job (quota-free).
One-call signup: issues a provisional key and emails a magic verification link.
Deletes the caller's account, per app: a verified key revokes every key of the identity behind it that carries the same label (each MapMap app labels its own key), and, when no other active key remains on the identity, deletes the account itself and erases its email, IP addresses and user agents. An unverified (`provisional`) key revokes only itself, and deletes the account only when it is the account's sole key: anyone who types an address can mint one, so it never speaks for the account. On the store-review identity any key deletes only itself, because that address is not a secret (security check M3). Idempotent: a retry with the same, now revoked, key answers 200 with `already_deleted`.
Key status for the calling agent (quota-free: polling it never consumes the free tier).
Sends a one-time code to an address for the calling email-less (`anonymous`) key. Nothing changes until the SAME key sends the code back to `POST /v1/keys/self/email/verify`; meanwhile `GET /v1/keys/self` shows the address as `pending_email`. Sending again (a corrected address, or a resend) replaces the pending address and voids the earlier code.
Proves the address: the calling email-less key sends back the code `POST /v1/keys/self/email` mailed. On success the address becomes this key's account's, and THIS key, and only this key, is lifted to `verified` on the free tier, which also unlocks offline downloads.
Mint (or rotate) the calling key's webhook signing secret (quota-free).
The emailed link's landing page. **Opening it changes nothing** (review of #1339, H1): mail security scanners and a single stray click open links, so a link that confirmed on GET could confirm a key a stranger asked for. The page shows the request (the app it said it came from, or that it named none, the time and the device class; no location is recorded) and confirms or refuses only on an explicit button, which POSTs to [`confirm_key`] or [`deny_key`].
Confirms the ONE key a link was mailed for, upgrading it to the verified free tier (or the plan already bought). Only an explicit press of the page's button reaches this (review of #1339, H1).
"This wasn't me": revokes the key a link was mailed for and spends the link. The owner of the address refuses a key somebody asked for against it (review of #1339, H1).
What the confirmation page shows: the request behind a link, without consuming it. A POST, so the token stays out of URLs and logs.
The calling key's own metered units, day by day and endpoint by endpoint (quota-free: reading it never spends units).
`POST /v1/x402/topup?usd={bundle}`.
static-maps
Rendered map images for callers that can look at a map but cannot run one: camera, overlays (encoded polyline, GeoJSON, markers) and format in the query string, or the GeoJSON overlay in a POST body. The gateway renders nothing itself: it checks the key, meters the call and proxies the same renderer the keyless website route uses, so the keyed image and the keyless one cannot disagree. The renderer's own ETag and Cache-Control pass through untouched. Standard price class, a flat block of units per image
styles
Hosted style API (MapMap Studio): versioned, immutable MapLibre styles compiled from sn-style theme documents. Compiled-style and theme reads are public and unmetered (browser map clients fetch them by bare URL); listing is authenticated and scoped to the caller's own styles; publishes are metered at the Standard price class and enforce ownership
`GET /styles`: the CALLER'S hosted styles with their latest versions.
`POST /styles`; create a style: validate and compile the theme, store it as version 1 under a freshly generated id.
`DELETE /styles/{id}`: remove a style and every version of it.
`GET /styles/{spec}`: a compiled MapLibre style.
`POST /styles/{id}`: publish a new immutable version of an existing style (existing versions are never modified).
`GET /styles/{id}/theme`: the latest theme document (the editable source a new version is published from; never cached).
territories
Metered territory update-channel downloads (signed static files; devices verify signatures and hashes themselves)
`GET /territories`: the signed channel index (`index.json`), byte exact so the detached signature verifies over the response body.
`GET /territories/{id}/{version}/layers/{addr}/{file}`: a content-addressed layer blob, streamed with a strong BLAKE3 ETag, single-range `Range` support and immutable cache headers.
`GET /territories/{id}/{version}/manifest`: a version's signed package manifest (`manifest.json`, exact signed bytes).
`GET /territories/{id}/{version}/manifest.sig`: the manifest's detached base64 ed25519 signature.
`GET /territories/index.sig`: detached base64 ed25519 signature over the exact bytes of `/territories`.
Submit a custom-region cut to the asynchronous lane.
`GET /v1/territories/{id}/index.json`: a custom region's own signed channel index (one territory, every version cut so far), exact bytes.
`GET /v1/territories/{id}/index.json.sig`: detached base64 ed25519 signature (region key) over the exact bytes of the region's index.
tiles
Hosted vector-tiles API: per-tile MVT, TileJSON and a MapLibre style from the territory PMTiles. Standard price class, metered per request
`GET /tiles/{territory}/{z}/{x}/{y}.mvt` (also `.pbf`): one vector tile.
`GET /tiles/{territory}/style.json`: a ready-to-render MapLibre style.
`GET /tiles/{territory}/tiles.json`: a TileJSON 3.0 document.
timezone
Timezone-at-coordinate: IANA zone id, UTC offset, DST offset and abbreviation at a given timestamp. Backed by Valhalla's own timezones.sqlite boundary database and chrono-tz's IANA rules. 501 unless the operator sets SN_TIMEZONE_SQLITE. Standard price class, metered per request
transit
Live public-transport positions for display: England local buses from the DfT Bus Open Data Service (BODS SIRI-VM), as GeoJSON for a bounding box, with the feed's freshness on every answer (a stale feed is a field, never an error) and the Open Government Licence v3.0 attribution. Also England bus and coach stops (NaPTAN) near a point and timetabled departures at a stop (BODS timetables), each departure optionally paired with a vehicle seen on its line heading towards the stop. Display only: no journey-time, timetable-routing or arrival-prediction answers. Standard price class, one unit per request; a browser (`maps`) key may call them. 501 unless the operator sets SN_TRANSIT_DIR (and, for stops and departures, builds the departures index in it)
voice
Guidance voice clips: synthesise-once, cache-forever audio for the closed navigation grammar. The app asks for the utterances a route will speak and plays the returned files; the gateway keeps every clip forever, so a sentence is synthesised once across every driver. Synthesis is metered one unit per NEW clip (cache hits are refunded); fetching a cached clip and listing the bank are key-authenticated and quota-free. 501 unless the operator sets SN_VOICE_DIR and at least one of SN_ELEVENLABS_API_KEY (ElevenLabs) and SN_TTS_URL (the self-hosted open-source voices). A clip answered by an open-source fallback voice carries its own hash and `fallback: true`, so clients take hashes from the response. The synthesis key can never ship in an app (ElevenAPI Terms), which is why this endpoint exists at all