Vector Tiles
Serve Plaza's OSM data as Mapbox Vector Tiles for use with MapLibre GL JS and other renderers.
Plaza serves OSM data as Mapbox Vector Tiles (MVT), compatible with MapLibre GL JS, Mapbox GL JS, or any MVT renderer.
Endpoint
Section titled “Endpoint”GET /api/v1/tiles/{z}/{x}/{y}Returns a application/vnd.mapbox-vector-tile protobuf.
Tile coordinates
Section titled “Tile coordinates”| Zoom | Tiles | Coverage per tile |
|---|---|---|
| 8 | ~66K | ~Region |
| 10 | ~1M | ~City |
| 14 | ~268M | ~Neighborhood |
| 18 | ~69B | ~Building |
| 22 | ~17T | ~Sub-building |
Plaza serves zoom 8–22. Requests below zoom 8 return an error. Higher zooms include finer detail (buildings, footpaths, addresses).
Layers
Section titled “Layers”| Layer | Contents |
|---|---|
nodes | Points of interest (amenities, shops, addresses, etc.) |
ways | Roads, buildings, parks, rivers, land use polygons |
Each feature includes osm_id and name (if the name tag exists).
MapLibre GL JS
Section titled “MapLibre GL JS”<!DOCTYPE html><html><head> <link href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" rel="stylesheet" /> <script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script> <style> #map { width: 100%; height: 100vh; } </style></head><body> <div id="map"></div> <script> const map = new maplibregl.Map({ container: 'map', center: [2.35, 48.86], zoom: 13, style: { version: 8, sources: { plaza: { type: 'vector', tiles: [ 'https://plaza.fyi/api/v1/tiles/{z}/{x}/{y}?api_key=YOUR_KEY' ], minzoom: 8, maxzoom: 22, }, }, layers: [ { id: 'ways', type: 'line', source: 'plaza', 'source-layer': 'ways', paint: { 'line-color': '#888', 'line-width': ['interpolate', ['linear'], ['zoom'], 10, 0.5, 18, 6], }, }, { id: 'nodes', type: 'circle', source: 'plaza', 'source-layer': 'nodes', minzoom: 14, paint: { 'circle-radius': 4, 'circle-color': '#e55e5e', }, }, ], }, }); </script></body></html>Authentication for tiles
Section titled “Authentication for tiles”Map renderers issue tile requests automatically and don’t support custom headers, so pass the API key as a query parameter:
https://plaza.fyi/api/v1/tiles/{z}/{x}/{y}?api_key=pk_live_abc123The x-api-key header still works for manual fetches.
Combining with your own data
Section titled “Combining with your own data”const map = new maplibregl.Map({ container: 'map', center: [-122.42, 37.78], zoom: 13, style: { version: 8, sources: { plaza: { type: 'vector', tiles: ['https://plaza.fyi/api/v1/tiles/{z}/{x}/{y}?api_key=YOUR_KEY'], minzoom: 8, maxzoom: 22, }, stores: { type: 'geojson', data: '/my-store-locations.geojson', }, }, layers: [ // Plaza base layers { id: 'ways', type: 'line', source: 'plaza', 'source-layer': 'ways', paint: { 'line-color': '#ccc', 'line-width': 1 }, }, // Your data on top { id: 'my-stores', type: 'circle', source: 'stores', paint: { 'circle-radius': 8, 'circle-color': '#ff4444', 'circle-stroke-color': '#fff', 'circle-stroke-width': 2, }, }, ], },});Caching
Section titled “Caching”Tiles are cacheable for 1 hour (max-age=3600). Map renderers handle this automatically.
For high-traffic apps, put a CDN (Cloudflare, Fastly, CloudFront) in front of the tile endpoint. Cache headers are already set correctly.