For Platform Providers
Population intelligence as infrastructure for your platform.
Learn more →1.4M+ spots. 210 DMAs. Back to 2019.
Every number grounded in the same population intelligence layer.
Try it →Every number shows its work.
See the data, the model, and the receipts behind each metric.
Methodology overview →Build the measurement layer for the physical world.
Engineering, science, and go-to-market roles across the company.
See open roles →Mint a tile grant from a server you control, hand the resulting TileJSON URL to MapLibre GL or Mapbox GL, and render Motionworks data layers directly in your customer-facing map — no proxy, no Carto credentials in your browser.
Motionworks data streams as Mapbox Vector Tiles (MVT) under the same per-product entitlement that gates JSON access — just a different transport. Paths is live today; other products follow as their tile workers ship.
Each tile-enabled product/reference family exposes a vector-tile
surface at /v2/<product>/tiles/. The same
per-product entitlement that gates JSON access gates tile access
— a Paths customer gets path-line vector tiles; a Placecast
customer would get building / collection-area tiles; etc. There is no
separate “vector tiles” SKU and no separate
subscription tier. Paths is the first — and
currently only — live tile surface; the others are on the
roadmap below.
Your server posts to
POST /v2/<product>/tiles/grants using either
an X-API-Key: mw_<64-hex> header or a
Supabase Authorization: Bearer <jwt>. The
response carries a grant_id and a TileJSON URL.
Grants are 0 credits.
The TileJSON URL is a capability URL — the grant id is
baked in and the response carries the
{z}/{x}/{y}.mvt tile template with a
short-lived ?token=<jwt> (24 h TTL).
MapLibre fetches tiles directly with that token; your
browser never sees the upstream Carto URL.
Mint the grant once on your backend; reuse the TileJSON URL for the whole session.
// 1. Server-side (Node, Worker, anything you control):
// const r = await fetch('https://api2.mworks.com/v2/paths/tiles/grants', {
// method: 'POST',
// headers: { 'X-API-Key': process.env.MW_API_KEY, 'Content-Type': 'application/json' },
// body: JSON.stringify({ tilesets: ['roadway_volumes_annual_2025_heatmap'] })
// });
// const { tile_json_url } = await r.json();
// 2. Client-side MapLibre:
map.addSource('mw-paths', { type: 'vector', url: tile_json_url });
map.addLayer({
id: 'mw-paths',
type: 'line',
source: 'mw-paths',
'source-layer': 'roadway_volumes_annual_2025_heatmap'
}); POST / GET / POST revoke
under /v2/<product>/tiles/grants.
X-API-Key: mw_<64-hex> or Supabase JWT..mvt fetch GET /v2/<product>/tiles/grants/:id/tilejson and
GET /v2/<product>/tiles/{layer}/{z}/{x}/{y}.mvt?token=<jwt>.
X-API-Key, no Authorization header.
Revoke a grant via
POST /v2/<product>/tiles/grants/:id/revoke —
revocation propagates within ~60 s. For instant kill, rotate the
tile-token signing key on the server (kills every outstanding token).
Keep tile tokens out of your logs. The
?token=<jwt> rides in the tile URL, so it can land in
request logs, error-tracker breadcrumbs, and proxy logs. Tokens are
short-lived (24 h) but you should still scrub the token
query param at your log/observability ingest — e.g. a Sentry
beforeBreadcrumb that strips ?token= from URL
breadcrumbs.
The first vector-tile surface is Paths
(/v2/paths/tiles/) — roadway-volume annual
heatmaps, lit by the same data behind the Motionworks
OBM traffic map demo. Places, Placecast,
Markets Reference, Displays, and Viewcast each get their own
/v2/<product>/tiles/ surface as the per-product
tile workers ship. Per-product roll-out timing lives in the
API reference; this page reflects what is
live today.
Sandbox keys are issued from the Motionworks console — same key works for the JSON API and for tile grants.