π¦ Dataset Tiles API
Upload your own geodata and serve it as a vector tile layer β overlaid on a basemap using the same Maps key. Globally cached, secure, and accessible via a simple tile URL.
βοΈ How It Works
Files are processed by tippecanoe on our servers and stored on our edge infrastructure. Tiles are typically ready within 5β10 seconds for small files.
pk_latlng_β¦ Maps key β one key for everything.
Basemap tiles β tiles.latlng.work/v1/tiles/{z}/{x}/{y}.pbf?key=pk_β¦Your dataset β tiles.latlng.work/v1/datasets/{id}/{z}/{x}/{y}.pbf?key=pk_β¦
π Common Use Cases
Parcel boundaries, zoning districts, flood zones overlaid on a property search map.
Delivery zones, service areas, route polygons β show customers which zone theyβre in.
Census tracts, school districts, city boundaries β without a GIS server.
Field survey points, habitat boundaries, sensor locations on an interactive map.
β¨ Live Demo Pre-loaded with a sample NYC dataset
The map below shows a real dataset overlaid on LatLng basemap tiles. Swap in your own key and dataset ID from the Datasets dashboard.
π Endpoints
Vector Tile (PBF)
Metadata (TileJSON)
Parameters
| Param | Type | Description |
|---|---|---|
id * | string | Dataset ID from the dashboard, e.g. ds_abc123xyz |
z * | integer | Zoom level 0β14 |
x * | integer | Tile column |
y * | integer | Tile row |
key * | string | Your Maps key (pk_latlng_β¦) β must belong to the dataset owner |
pk_latlng_β¦). Secret keys are rejected with 403 to prevent accidental exposure.π» Code Examples
L.tileLayer only renders raster (PNG/JPEG) tiles. LatLng basemap tiles are vector (PBF) β use OpenStreetMap raster tiles for the basemap, or switch to the MapLibre tab to use LatLng tiles for everything.const MY_KEY = 'pk_latlng_your_maps_key';
const DATASET_ID = 'ds_your_dataset_id';
const map = L.map('map').setView([40.71, -74.01], 11);
// Basemap β OSM raster tiles (Leaflet cannot render vector PBF tiles)
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{ attribution: 'Β© OpenStreetMap contributors', maxZoom: 19 }
).addTo(map);
// Your dataset as an overlay via leaflet.vectorgrid
const datasetLayer = L.vectorGrid.protobuf(
`https://tiles.latlng.work/v1/datasets/${DATASET_ID}/{z}/{x}/{y}.pbf?key=${MY_KEY}`,
{
vectorTileLayerStyles: {
[DATASET_ID]: {
color: '#22c55e',
weight: 2,
opacity: 1,
fill: true,
fillColor: '#22c55e',
fillOpacity: 0.25,
}
}
}
).addTo(map);import maplibregl from 'maplibre-gl';
const MY_KEY = 'pk_latlng_your_maps_key';
const DATASET_ID = 'ds_your_dataset_id';
const map = new maplibregl.Map({
container: 'map',
style: `https://tiles.latlng.work/v1/style/dark?key=${MY_KEY}`,
center: [-74.01, 40.71],
zoom: 11,
});
map.on('load', () => {
map.addSource('my-dataset', {
type: 'vector',
tiles: [
`https://tiles.latlng.work/v1/datasets/${DATASET_ID}/{z}/{x}/{y}.pbf?key=${MY_KEY}`
],
minzoom: 0,
maxzoom: 14,
});
map.addLayer({
id: 'dataset-fill',
type: 'fill',
source: 'my-dataset',
'source-layer': DATASET_ID,
paint: { 'fill-color': '#22c55e', 'fill-opacity': 0.4 },
});
map.addLayer({
id: 'dataset-line',
type: 'line',
source: 'my-dataset',
'source-layer': DATASET_ID,
paint: { 'line-color': '#22c55e', 'line-width': 2 },
});
});const MY_KEY = 'pk_latlng_your_maps_key';
const DATASET_ID = 'ds_your_dataset_id';
// Fetch metadata (bounds, zoom range, layer name)
const meta = await fetch(
`https://tiles.latlng.work/v1/datasets/${DATASET_ID}/metadata?key=${MY_KEY}`
).then(r => r.json());
console.log(meta.bounds, meta.minzoom, meta.maxzoom);
// Fetch a single tile as ArrayBuffer
const tile = await fetch(
`https://tiles.latlng.work/v1/datasets/${DATASET_ID}/7/38/48.pbf?key=${MY_KEY}`
).then(r => r.arrayBuffer());
// Decode with @mapbox/vector-tile or pbf libraryπ Plan Limits
| Plan | Datasets | Max file size | Tile requests |
|---|---|---|---|
| Free | 3 | 50 MB | Unlimited (CDN-cached) |
| Pro | 50 | 1 GB | Unlimited (CDN-cached) |
| Enterprise | Unlimited | 5 GB | Unlimited (CDN-cached) |