Features Pricing Docs Contact Dashboard

API Documentation

Geocoding, Places Search, and Map Tiles β€” everything you need to build location-aware apps.

πŸ”‘ Authentication

All API requests require an API key. There are two types of keys:

Key Type Prefix Use Case
Server Key latlng_ All APIs β€” geocoding, reverse, places, tiles. Keep secret in backend code.
Maps Key pk_latlng_ Map tiles, static maps, and autosuggest. Safe to embed in client-side code. Can be domain-restricted.

Header Authentication (Server Key)

X-Api-Key: latlng_your_key_here

Query Parameter (Maps Key)

https://tiles.latlng.work/v1/metadata?key=pk_latlng_your_key

The X-Api-Key header is the recommended format. You can also pass the key as a query parameter (?api_key=YOUR_KEY) for backward compatibility.

Get your API keys from the dashboard.

🌍 Forward Geocoding

Convert an address or place name into geographic coordinates.

GET https://api.latlng.work/api

Parameters

Parameter Type Description
q required string The address or place name to geocode
limit integer Maximum number of results (default: 10)
lang string Language for results (e.g., "en", "de", "fr")

Example Request

curl "https://api.latlng.work/api?q=Seattle,WA" \
  -H "X-Api-Key: your_api_key"

Example Response

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-122.3321, 47.6062]
      },
      "properties": {
        "name": "Seattle",
        "state": "Washington",
        "country": "United States",
        "type": "city"
      }
    }
  ]
}

πŸ“ Reverse Geocoding

Convert geographic coordinates into a human-readable address.

GET https://api.latlng.work/reverse

Parameters

Parameter Type Description
lat required number Latitude coordinate
lon required number Longitude coordinate

Example Request

curl "https://api.latlng.work/reverse?lat=47.6062&lon=-122.3321" \
  -H "X-Api-Key: your_api_key"

πŸ“Œ Places Nearby

Find points of interest near a location. Places data is powered by OpenStreetMap via Photon.

GET https://api.latlng.work/v1/places/nearby

Parameters

Parameter Type Description
lat required number Latitude of the center point
lon required number Longitude of the center point
radius integer Search radius in meters (default: 1000, max: 5000)
category string Filter by category (e.g., "hotel", "restaurant")
limit integer Maximum results to return (default: 20)

Example Request

curl "https://api.latlng.work/v1/places/nearby?lat=47.6062&lon=-122.3321&radius=1000&limit=5" \
  -H "X-Api-Key: your_api_key"

Example Response

{
  "type": "nearby",
  "center": { "lat": 47.6062, "lon": -122.3321 },
  "radius": 1000,
  "count": 2,
  "places": [
    {
      "name": "Pike Place Market",
      "lat": 47.6097,
      "lon": -122.3425,
      "category": "marketplace",
      "distance_m": 328
    },
    {
      "name": "Starbucks Reserve Roastery",
      "lat": 47.6140,
      "lon": -122.3281,
      "category": "cafe",
      "distance_m": 912
    }
  ]
}

πŸ” Places Search

Search for places by name with optional location bias and category filtering.

GET https://api.latlng.work/v1/places/search

Parameters

Parameter Type Description
q required string Search query (e.g., "Starbucks")
lat number Latitude for location bias
lon number Longitude for location bias
category string Filter by category
country string Filter by country code (e.g., "US")
limit integer Maximum results (default: 10)

Example Request

curl "https://api.latlng.work/v1/places/search?q=Starbucks&lat=47.60&lon=-122.33&limit=5" \
  -H "X-Api-Key: your_api_key"

Example Response

{
  "type": "search",
  "query": "Starbucks",
  "count": 2,
  "places": [
    {
      "name": "Starbucks",
      "lat": 47.6101,
      "lon": -122.3420,
      "category": "cafe",
      "distance_m": 845,
      "match_score": 1.0
    }
  ]
}

πŸ’‘ Places Autosuggest

Get place name suggestions as the user types. Ideal for search-as-you-type UIs.

GET https://api.latlng.work/v1/places/autosuggest

Parameters

Parameter Type Description
q required string Partial query (min 2 characters)
lat number Latitude for location bias
lon number Longitude for location bias
limit integer Maximum suggestions (default: 5)

Example Request

curl "https://api.latlng.work/v1/places/autosuggest?q=star&lat=47.60&lon=-122.33" \
  -H "X-Api-Key: your_api_key"

Example Response

{
  "type": "autosuggest",
  "query": "star",
  "suggestions": [
    { "name": "Starbucks", "category": "cafe", "similarity": 0.85 },
    { "name": "Star Nails", "category": "beauty_salon", "similarity": 0.72 }
  ]
}

πŸ“‚ Places Categories

List all available place categories you can use to filter results. Categories are based on OpenStreetMap tags. View full categories list β†’

GET https://api.latlng.work/v1/places/categories

Example Request

curl "https://api.latlng.work/v1/places/categories" \
  -H "X-Api-Key: your_api_key"

Example Response

{
  "categories": [
    { "name": "restaurant", "count": 584210 },
    { "name": "cafe", "count": 312045 },
    { "name": "hotel", "count": 198432 }
  ]
}

πŸ—ΊοΈ Map Tiles API

Serve OpenStreetMap-based vector tiles for MapLibre GL JS. Uses a Maps Key (pk_latlng_) passed as a query parameter.

TileJSON Metadata

GET https://tiles.latlng.work/v1/metadata?key=pk_latlng_...

Returns a TileJSON spec describing tile sources, bounds, and attribution. This is the URL you pass to MapLibre's source.url.

Vector Tiles

GET https://tiles.latlng.work/v1/tiles/{z}/{x}/{y}.pbf?key=pk_latlng_...

Returns Protobuf-encoded vector tiles. Normally accessed by MapLibre automatically β€” you don't call this directly.

MapLibre GL JS Integration

<link rel="stylesheet" href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css">
<script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/protomaps-themes-base"></script>

<div id="map" style="width:100%; height:400px;"></div>

<script>
const map = new maplibregl.Map({
  container: 'map',
  style: {
    version: 8,
    glyphs: 'https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf',
    sprite: 'https://protomaps.github.io/basemaps-assets/sprites/v4/light',
    sources: {
      protomaps: {
        type: 'vector',
        url: 'https://tiles.latlng.work/v1/metadata?key=pk_latlng_YOUR_KEY'
      }
    },
    layers: protomapsL.layers('protomaps', protomapsL.namedFlavor('light'), { lang: 'en' })
  },
  center: [-122.33, 47.61],
  zoom: 13
});
</script>

⚠️ Rate Limits

Usage is tracked per-user across all API keys with a unified quota β€” all API calls (geocoding, reverse, places, tiles) count toward one shared pool.

Plan Quota Period
Free 3,000 total API calls Per day
Pro 1,000,000 total API calls Per month
Enterprise Custom Custom

Every geocode, reverse geocode, places search, and tile request counts equally toward your quota.

Rate limit headers are included in every response:

Header Description
X-RateLimit-Limit Your plan's total request limit for the current period
X-RateLimit-Remaining Requests remaining in current period (across all API types)

πŸ—ΊοΈ Static Maps API

Generate a static map image (PNG or JPEG) from a URL. Great for email previews, social cards, and server-side rendering.

GET https://api.latlng.work/v1/static

Parameters

ParameterTypeDefaultDescription
key *stringβ€”Your API key (header or query param)
centerstringβ€”Map center as lng,lat. Required unless using bbox.
zoomnumberβ€”Zoom level 0–20. Required unless using bbox.
bboxstringβ€”Auto-fit to bounding box minLng,minLat,maxLng,maxLat. Overrides center/zoom.
widthinteger800Image width in pixels (max 2048)
heightinteger600Image height in pixels (max 2048)
stylestringdarklight Β· dark Β· grayscale Β· black Β· white Β· contrast
formatstringpngpng or jpeg
markersstringβ€”Pipe-separated: lng,lat,color,label|lng,lat,color,label
pathstringβ€”Polyline: weight:color:opacity|lng,lat|lng,lat|... (repeatable)
geojsonstringβ€”URL-encoded GeoJSON to overlay on the map

Examples

Simple map centered on NYC:

https://api.latlng.work/v1/static
  ?center=-74.006,40.7128
  &zoom=12
  &width=800&height=400
  &style=dark
  &key=YOUR_KEY

Map with a marker:

https://api.latlng.work/v1/static
  ?center=-74.006,40.7128
  &zoom=14
  &markers=-74.006,40.7128,22c55e,A
  &key=YOUR_KEY

Auto-fit to a bounding box:

https://api.latlng.work/v1/static
  ?bbox=-74.25,40.49,-73.7,40.92
  &width=1200&height=600
  &style=light
  &key=YOUR_KEY

JavaScript fetch example:

const params = new URLSearchParams({
  center: '-74.006,40.7128',
  zoom: '12',
  width: '800',
  height: '400',
  style: 'dark',
  key: 'YOUR_KEY'
});
const img = document.createElement('img');
img.src = `https://api.latlng.work/v1/static?${params}`;
document.body.appendChild(img);

πŸ“¦ Dataset Tiles API

Upload your own geodata (GeoJSON, GPX, KML, Shapefile, GeoPackage) via the dashboard and serve it as vector tiles. Access requires a Maps key (pk_latlng_...) that belongs to the dataset owner.

Tile Endpoint

GET https://tiles.latlng.work/v1/datasets/{id}/{z}/{x}/{y}.pbf

Metadata Endpoint

GET https://tiles.latlng.work/v1/datasets/{id}/metadata
ParameterTypeDescription
id *stringDataset ID from the dashboard (e.g. ds_abc123...)
z *integerTile zoom level (0–14)
x *integerTile X coordinate
y *integerTile Y coordinate
key *stringYour Maps key (pk_latlng_...) as a query parameter

Usage with Leaflet

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

// Base tiles
L.tileLayer(`https://tiles.latlng.work/v1/tiles/{z}/{x}/{y}.pbf?key=${MY_KEY}`).addTo(map);

// Your dataset as a vector tile layer (requires Leaflet.VectorGrid)
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, fillOpacity: 0.4 }
    }
  }
).addTo(map);

Usage with MapLibre GL JS

const MY_KEY = 'pk_latlng_your_maps_key';
const DATASET_ID = 'ds_your_dataset_id';

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: 'my-dataset-layer',
  type: 'fill',
  source: 'my-dataset',
  'source-layer': DATASET_ID,
  paint: {
    'fill-color': '#22c55e',
    'fill-opacity': 0.5
  }
});

Plan Limits

PlanDatasetsMax File Size
Free350 MB
Pro501 GB
EnterpriseUnlimited5 GB

❌ Error Codes

Code Description
400 Bad Request β€” Missing or invalid parameters
401 Unauthorized β€” Invalid or missing API key
403 Forbidden β€” Public key used on server-only endpoint, or domain not allowed
429 Too Many Requests β€” Rate limit exceeded
500 Internal Server Error