Free, no-key HTTP API for outdoor maps and routing: global elevation, vector basemap tiles, contour and hiking-network overlays, outdoor POIs, place search, OpenStreetMap trail relations, snow forecasts, and trail-aware routing. These are the exact endpoints behind the TrailSplits Route Planner.
The TrailSplits API provides free access to global elevation data, vector tiles, place search, routing, snow forecasts, trail relations, and outdoor POIs. Everything is derived from open data — the Copernicus 30 m DEM for elevation and OpenStreetMap planet extracts for everything else — and served from a single origin with CDN caching and CORS enabled.
Usage policy: free for hobby, research, and non-commercial use. Please attribute TrailSplits and © OpenStreetMap contributors. For commercial use or higher quotas, reach out.
Three copy-paste calls to confirm connectivity and see the shape of the data:
# 1. Health check (plain-text "ok")
curl -sS https://api.trailsplits.com/healthz
# 2. List available dataset releases
curl -sS https://api.trailsplits.com/tiles/v1/catalog
# 3. Sample elevation (meters) for two points — returns JSON
curl -sS "https://api.trailsplits.com/tiles/v1/elevation/current/sample?points=46.5369,12.1352|46.5193,12.0106"
# 4. Fetch one TerrainRGB elevation tile (z9 over the Dolomites)
curl -sS -o terrain.png "https://api.trailsplits.com/tiles/v1/terrainrgb/current/9/271/186.png" All endpoints are served from https://api.trailsplits.com over HTTPS, fronted by the Cloudflare
CDN. Tile and style responses are edge-cached; dynamic JSON endpoints are computed per request.
Tile datasets are versioned by an immutable release name. Use current as a
mutable alias that always points to the latest active release, or pin an explicit release for reproducibility.
Style JSON and assets for MapLibre GL clients. The planner fetches the style object on load and renders the basemap from the bundled PMTiles source.
| Method | Endpoint |
|---|---|
| GET | /styles/<release>/trailsplits_openmaptiles_style.json |
| GET | /styles/<release>/glyphs/{fontstack}/{range}.pbf |
| GET | /styles/<release>/sprites/trailsplits.json |
| GET | /styles/<release>/sprites/trailsplits.png |
curl -sS "https://api.trailsplits.com/styles/current/trailsplits_openmaptiles_style.json" | head -c 300 A single PMTiles archive with global vector tiles in the OpenMapTiles schema. PMTiles uses HTTP Range requests, so clients fetch only the bytes they need — no per-tile server round-trips.
| Method | Endpoint |
|---|---|
| GET | /pmtiles/<release>/tiles/openmaptiles_planet.pmtiles |
| GET | /pmtiles/current/tiles/openmaptiles_planet.pmtiles (alias) |
Use it directly in MapLibre GL with the PMTiles protocol:
pmtiles://https://api.trailsplits.com/pmtiles/current/tiles/openmaptiles_planet.pmtiles Validate that Range requests work (expect HTTP/2 206 Partial Content):
curl -sS -o /dev/null -D - -r 0-1023 \
"https://api.trailsplits.com/pmtiles/current/tiles/openmaptiles_planet.pmtiles" Global elevation encoded as Mapbox TerrainRGB PNG tiles. The planner uses these for hillshade rendering and 3D terrain exaggeration. Tiles are built to zoom 12; request higher zooms and the server overzooms from the parent tile.
| Method | Endpoint | Format |
|---|---|---|
| GET | /tiles/v1/terrainrgb/<release>/{z}/{x}/{y}.png | image/png |
| GET | /tiles/v1/terrainrgb/<release>/metadata.json | JSON |
curl -sS -I "https://api.trailsplits.com/tiles/v1/terrainrgb/current/9/271/186.png"
curl -sS "https://api.trailsplits.com/tiles/v1/terrainrgb/current/metadata.json" Minimal MapLibre style for hillshade + 3D terrain:
{
"version": 8,
"sources": {
"dem": {
"type": "raster-dem",
"tiles": ["https://api.trailsplits.com/tiles/v1/terrainrgb/current/{z}/{x}/{y}.png"],
"tileSize": 256,
"encoding": "mapbox",
"maxzoom": 12
}
},
"terrain": { "source": "dem", "exaggeration": 1.2 },
"layers": [
{ "id": "hillshade", "type": "hillshade", "source": "dem" }
]
} Sample elevation (meters) for a list of coordinates from the same TerrainRGB data — no need to decode tiles yourself. The planner uses this to build elevation profiles and compute ascent/descent.
| Method | Endpoint |
|---|---|
| GET | /tiles/v1/elevation/<release>/sample |
Query parameters:
points (required) — lat,lon|lat,lon|... (up to 2048 points)z (optional, default 13) — sampling zoom; clamped to the dataset max zoom (12)encoding (optional, default mapbox) — mapbox or terrariumcurl -sS "https://api.trailsplits.com/tiles/v1/elevation/current/sample?encoding=mapbox&points=46.5369,12.1352|46.5193,12.0106" Response:
{
"release": "current",
"z": 12,
"z_requested": 13,
"encoding": "mapbox",
"points": [
{ "lat": 46.5369, "lon": 12.1352, "elevation_m": 1193.3 },
{ "lat": 46.5193, "lon": 12.0106, "elevation_m": 2098.8 }
]
}Calls api.trailsplits.com directly from your browser (CORS enabled).
(click Fetch)Vector contour lines (Mapbox Vector Tiles / Protobuf), generated from the Copernicus DEM. The planner renders these as styled line layers with labels at major (100 m) and minor intervals.
| Method | Endpoint | Format |
|---|---|---|
| GET | /tiles/v1/contours/<release>/{z}/{x}/{y}.pbf | application/x-protobuf |
| GET | /tiles/v1/contours/<release>/metadata.json | JSON |
curl -sS "https://api.trailsplits.com/tiles/v1/contours/current/metadata.json"
curl -sS -I "https://api.trailsplits.com/tiles/v1/contours/current/13/4412/3076.pbf" Vector overlay of hiking and cycling trail networks extracted from OpenStreetMap route relations. Feature
properties include the network tier (iwn/nwn/rwn/lwn),
trail name, ref, operator, osmc_symbol, and surface tags where available.
| Method | Endpoint | Format |
|---|---|---|
| GET | /tiles/v1/hiking-network/<release>/{z}/{x}/{y}.pbf | application/x-protobuf |
| GET | /tiles/v1/hiking-network/<release>/metadata.json | JSON |
curl -sS "https://api.trailsplits.com/tiles/v1/hiking-network/current/metadata.json"
curl -sS -I "https://api.trailsplits.com/tiles/v1/hiking-network/current/12/2206/1538.pbf" Points of interest for the outdoors — water sources, huts and shelters, parking, viewpoints, mountain passes, transit stops, and more — extracted from OpenStreetMap. Served as a vector tile overlay that the planner renders directly.
| Method | Endpoint | Format |
|---|---|---|
| GET | /tiles/v1/outdoor-pois/<release>/{z}/{x}/{y}.pbf | application/x-protobuf |
| GET | /tiles/v1/outdoor-pois/<release>/metadata.json | JSON |
curl -sS "https://api.trailsplits.com/tiles/v1/outdoor-pois/current/metadata.json"
curl -sS -I "https://api.trailsplits.com/tiles/v1/outdoor-pois/current/12/2206/1538.pbf" Query POIs inside a rectangle and get JSON back — handy for server-side lookups when you don't want to
decode vector tiles. Returns a GeoJSON-style FeatureCollection with kind, name, ele (metres, nullable), and lat/lon.
| Method | Endpoint |
|---|---|
| GET | /pois/v1/bbox |
Query parameters (note: min_lon/max_lon, not lng):
min_lat, min_lon, max_lat, max_lon (required) — the bounding boxkind (optional) — comma-separated filter, e.g. water,hut,parking,shelter,viewpointlimit (optional) — max features to returncurl -sS "https://api.trailsplits.com/pois/v1/bbox?min_lat=46.5&max_lat=46.55&min_lon=12.0&max_lon=12.05&kind=water,hut&limit=3" Response:
{
"type": "FeatureCollection",
"count": 3,
"features": [
{ "kind": "water", "name": null, "ele": null, "lat": 46.527856, "lon": 12.001694 },
{ "kind": "water", "name": null, "ele": null, "lat": 46.522098, "lon": 12.009054 },
{ "kind": "hut", "name": "Rifugio", "ele": 2010, "lat": 46.523744, "lon": 12.037963 }
]
} Aerial/satellite raster tiles (Esri World Imagery), fetched and cached at the origin. Useful as an alternate basemap or for verifying terrain against the vector map.
| Method | Endpoint | Format |
|---|---|---|
| GET | /tiles/v1/satellite/arcgis/world-imagery/{z}/{x}/{y}.jpg | image/jpeg |
curl -sS -o sat.jpg "https://api.trailsplits.com/tiles/v1/satellite/arcgis/world-imagery/12/2206/1538.jpg" Discover the available releases for every dataset (TerrainRGB, contours, snow, hiking-network, outdoor
POIs, and more). Use a listed release name to pin a dataset, or stick with current.
| Method | Endpoint |
|---|---|
| GET | /tiles/v1/catalog |
| GET | /healthz — liveness check (plain-text ok) |
curl -sS "https://api.trailsplits.com/tiles/v1/catalog" Full-text place search and reverse geocoding over an OpenStreetMap-derived gazetteer (towns, villages, peaks, lakes, huts, stations, and other named features). This powers the search box in the planner.
| Method | Endpoint | Description |
|---|---|---|
| GET | /search/v1/forward?q=<query> | Forward search by name (prefix matching) |
| GET | /search/v1/reverse?lat=&lon= | Nearest named features to a point |
| GET | /search/v1/healthz | Health check with index stats |
Parameters (forward):
q (required) — search textlimit (optional, default 10)bbox (optional) — minLon,minLat,maxLon,maxLat to restrict resultsbias_bbox (optional) — soft spatial boost toward a boxParameters (reverse): lat, lon (required), limit (optional).
# Forward search
curl -sS "https://api.trailsplits.com/search/v1/forward?q=Zermatt&limit=2"
# Reverse geocode (nearest named features)
curl -sS "https://api.trailsplits.com/search/v1/reverse?lat=46.0207&lon=7.7491&limit=2" Forward response (center is [lon, lat]):
{
"query": "Zermatt",
"features": [
{ "id": 74378, "name": "Zermatt", "kind": "town", "center": [7.749254, 46.0212076] },
{ "id": 4290771, "name": "Zermatten", "kind": "locality", "center": [7.914665, 46.1865914] }
]
} Named hiking and cycling trail relations from OpenStreetMap. Search returns lightweight results (with a representative point); fetch a single relation by OSM id to get the full geometry plus distance, ascent, network tier, and bounding box.
| Method | Endpoint | Description |
|---|---|---|
| GET | /trails/v1/search?q=<query> | Full-text search by name or ref |
| GET | /trails/v1/relation/<osm_id> | Single relation with full geometry |
| GET | /trails/v1/bbox?min_lat=&min_lng=&max_lat=&max_lng= | Trails intersecting a bounding box |
| GET | /trails/v1/healthz | Health check with relation counts |
Parameters (search): q (required), limit (default 20, max 100), type (hiking | bicycle).
Parameters (bbox): min_lat, min_lng, max_lat, max_lng (note: lng, not lon), plus optional limit and type.
# Search for a trail by name
curl -sS "https://api.trailsplits.com/trails/v1/search?q=Tour+du+Mont+Blanc&limit=1"
# Full geometry for one relation
curl -sS "https://api.trailsplits.com/trails/v1/relation/9678362" | head -c 400
# Trails intersecting a bounding box (note min_lng/max_lng)
curl -sS "https://api.trailsplits.com/trails/v1/bbox?min_lat=45.7&min_lng=6.7&max_lat=46.1&max_lng=7.1&type=hiking&limit=10" Search response (GeoJSON; full geometry only via /relation/<id>):
{
"type": "FeatureCollection",
"query": "Tour du Mont Blanc",
"features": [
{
"type": "Feature",
"properties": {
"osm_relation_id": 9678362,
"route_type": "hiking",
"name": "Tour du Mont Blanc - Itinéraire principal",
"ref": "TMB-IP", "network": "rwn", "tier": 2,
"distance_km": 166.05,
"bbox": [6.706605, 45.696487, 7.12832, 46.058471]
},
"geometry": { "type": "Point", "coordinates": [6.917463, 45.877479] }
}
]
} Snow-coverage tiles and route-level snow summaries, fusing satellite classification with weather-model
data. Coverage is best at higher elevations during winter; outside snow conditions the summary reports unavailable rather than guessing.
| Method | Endpoint | Format |
|---|---|---|
| GET | /tiles/v1/snow/<release>/{z}/{x}/{y}.png | image/png |
| GET | /tiles/v1/snow/<release>/metadata.json | JSON |
curl -sS "https://api.trailsplits.com/tiles/v1/snow/current/metadata.json" Compute a snow summary for a list of sampled route points.
| Method | Endpoint |
|---|---|
| GET | /tiles/v1/snow/route-forecast |
Parameters: points (required, lat,lon|..., max 512), release (default current), z (default 13), encoding (default mapbox).
curl -sS "https://api.trailsplits.com/tiles/v1/snow/route-forecast?points=46.5369,12.1352|46.5193,12.0106" Trail-aware route calculation powered by Valhalla. The planner
calls a SvelteKit server proxy at /api/route (which adds provider fallback and trail tuning);
external clients can call the Valhalla origin directly.
| Method | Endpoint |
|---|---|
| POST | /route/v1 |
Supports Valhalla costings pedestrian, bicycle, and auto.
# Walking route in the Dolomites
curl -sS -X POST "https://api.trailsplits.com/route/v1" \
-H "Content-Type: application/json" \
--data-raw '{
"locations": [
{"lat": 46.5369, "lon": 12.1352},
{"lat": 46.5193, "lon": 12.0106}
],
"costing": "pedestrian",
"directions_options": {"units": "kilometers", "language": "en", "format": "osrm"}
}' | head -c 600; echo Server-rendered PNG map images over the TrailSplits basemap. Used for social/Open Graph cards and SEO previews; handy for any "snapshot of this area/route" use case.
| Method | Endpoint |
|---|---|
| POST | /static-map/render |
Parameters (JSON body):
width, height — output size in pixelsbbox (optional) — [minLon, minLat, maxLon, maxLat]center (optional) — [lon, lat] with zoompixelRatio (optional) — 1 or 2geojson (optional) — a LineString or FeatureCollection to overlaycurl -sS -X POST "https://api.trailsplits.com/static-map/render" \
-H "Content-Type: application/json" \
--data-raw '{
"width": 1200,
"height": 630,
"bbox": [11.9, 46.5, 12.2, 46.6],
"pixelRatio": 2
}' -o dolomites.png Yes. All endpoints are free for hobby, research, and non-commercial projects. Please attribute TrailSplits and OpenStreetMap. For commercial use or higher quotas, get in touch.
No. Every endpoint is public and requires no API key or token. Requests are served over HTTPS with permissive CORS headers, so you can call them directly from the browser.
Elevation comes from the Copernicus 30 m DEM, encoded as Mapbox TerrainRGB tiles. Vector tiles, trails, POIs, and search are derived from OpenStreetMap planet data. Routing is powered by self-hosted Valhalla.
Tile datasets are versioned by an immutable release name. Use the mutable alias "current" to always read the latest active release, or pin a specific release for reproducibility.
Tile and style responses are cached at the edge via Cloudflare CDN. Dynamic JSON endpoints (search, elevation sampling, routing, snow forecasts) are computed per request — keep payloads reasonable and cache on your side where possible.
These endpoints power the free route planner and our browser-based trail tools (GPX simplifier, elevation profiler, GAP calculator, and more). If you build something with the API, we'd love to hear about it — please attribute TrailSplits and © OpenStreetMap contributors.