Skip to content
GuidesBlogPlaygroundDashboard
Working with Data

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.

GET /api/v1/tiles/{z}/{x}/{y}

Returns a application/vnd.mapbox-vector-tile protobuf.

ZoomTilesCoverage 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).

LayerContents
nodesPoints of interest (amenities, shops, addresses, etc.)
waysRoads, buildings, parks, rivers, land use polygons

Each feature includes osm_id and name (if the name tag exists).

<!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>

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_abc123

The x-api-key header still works for manual fetches.

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,
},
},
],
},
});

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.