Developer API / Examples / Reference
REFERENCE · REGISTRY 1.6.0
API reference
Every call the API answers, each with a working example in curl, JavaScript and Python and a map to try it on. Every call is checked by a live probe against the public API. Weather is served from https://trailsplits.com, everything else from https://api.trailsplits.com. New fields can appear at any time; breaking changes are announced on the changelog.
Download OpenAPI JSON · TypeScript client · Postman collection (Bruno and Insomnia import it) · Working examples (ZIP)
You don't need a key to try: 500 credits a day per address. A free key from the API console counts calls against your project. Start with the quickstart; the conventions cover coordinate order, units, errors and limits. Use follows the API terms and the plan limits.
GET
Tile gateway health
/healthz
Public edge observation: text ok, not JSON. Origin paths/handlers can differ; health does not establish dataset freshness.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/healthz' {
"get": {
"operationId": "health",
"summary": "Tile gateway health",
"description": "Public edge observation: text ok, not JSON. Origin paths/handlers can differ; health does not establish dataset freshness.",
"tags": [
"Developer preview"
],
"security": [],
"parameters": [],
"responses": {
"200": {
"description": "Public gateway answers.",
"content": {
"text/plain": {
"schema": {
"type": "string",
"enum": [
"ok"
]
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Published artifact identities
/pmtiles/current/manifest.json
Resolve each artifact independently. Only the three demo-required artifact shapes are specified here; additional artifacts/metadata are retained. Missing required artifacts prevent this integration. Null/absent source dates stay unknown; retained URLs may retire.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/pmtiles/current/manifest.json' {
"get": {
"operationId": "manifest",
"summary": "Published artifact identities",
"description": "Resolve each artifact independently. Only the three demo-required artifact shapes are specified here; additional artifacts/metadata are retained. Missing required artifacts prevent this integration. Null/absent source dates stay unknown; retained URLs may retire.",
"tags": [
"Developer preview"
],
"security": [],
"parameters": [],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Manifest"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"artifacts": {
"type": "object",
"properties": {
"basemap": {
"$ref": "#/components/schemas/Artifact"
},
"terrain": {
"$ref": "#/components/schemas/Artifact"
},
"styles": {
"$ref": "#/components/schemas/StyleArtifact"
}
},
"required": [
"basemap",
"terrain",
"styles"
],
"additionalProperties": true
}
},
"required": [
"artifacts"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Artifact status verdict
/tiles/v1/status
artifact-status/1 producer verdict. Source-bound fresh can have a null source date; available=false is an unavailable manifest, not proof of freshness. Unknown is distinct from stale.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/tiles/v1/status' {
"get": {
"operationId": "status",
"summary": "Artifact status verdict",
"description": "artifact-status/1 producer verdict. Source-bound fresh can have a null source date; available=false is an unavailable manifest, not proof of freshness. Unknown is distinct from stale.",
"tags": [
"Developer preview"
],
"security": [],
"parameters": [],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Status"
}
}
}
},
"500": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"artifact-status/1"
]
},
"checked_at": {
"type": "string"
},
"available": {
"type": "boolean"
},
"stale": {
"type": "array",
"items": {
"type": "string"
}
},
"artifacts": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/StatusEntry"
}
}
},
"required": [
"schema",
"checked_at",
"available",
"stale",
"artifacts"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Terrain pixel sampling
/tiles/v1/elevation/{release}/sample
Pipe-separated lat,lon. Producer accepts up to 2048 points, clamps requested zoom to available backing data and returns one modelled metre height per point. null is missing, never zero. Does not densify or smooth a line. Example consumers impose smaller bounds. Unknown accuracy/source resolution is not surveyed truth.
| Name / location | Contract |
|---|---|
release · path · required | Published terrain version, or mutable current. Demo resolves/pins a version. |
points · query · required | 1–2048 lat,lon pairs separated by |; example uses 8/16/32. |
z · query | Requested zoom; response z is the effective zoom. |
encoding · query | Use mapbox for the published terrain. Other encoding is compatibility input, not a second dataset. |
Run the elevation profile example to see heights and unknown gaps.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
# Replace TERRAIN_RELEASE with artifacts.terrain.version from the manifest.
curl --fail-with-body 'https://api.trailsplits.com/tiles/v1/elevation/TERRAIN_RELEASE/sample?points=46.5369000%2C12.1352000%7C46.5367714%2C12.1348857%7C46.5366429%2C12.1345714%7C46.5365143%2C12.1342571%7C46.5363857%2C12.1339429%7C46.5362571%2C12.1336286%7C46.5361286%2C12.1333143%7C46.5360000%2C12.1330000&z=12&encoding=mapbox' {
"get": {
"operationId": "elevation",
"summary": "Terrain pixel sampling",
"description": "Pipe-separated lat,lon. Producer accepts up to 2048 points, clamps requested zoom to available backing data and returns one modelled metre height per point. null is missing, never zero. Does not densify or smooth a line. Example consumers impose smaller bounds. Unknown accuracy/source resolution is not surveyed truth.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [
{
"name": "release",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Published terrain version, or mutable current. Demo resolves/pins a version."
},
{
"name": "points",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "1–2048 lat,lon pairs separated by |; example uses 8/16/32."
},
{
"name": "z",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 0,
"maximum": 22,
"default": 13
},
"description": "Requested zoom; response z is the effective zoom."
},
{
"name": "encoding",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": [
"mapbox",
"terrarium"
],
"default": "mapbox"
},
"description": "Use mapbox for the published terrain. Other encoding is compatibility input, not a second dataset."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Elevation"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"release": {
"type": "string"
},
"z": {
"type": "integer",
"minimum": 0,
"maximum": 22
},
"z_requested": {
"type": "integer"
},
"encoding": {
"type": "string",
"enum": [
"mapbox",
"terrarium"
]
},
"points": {
"type": "array",
"items": {
"type": "object",
"properties": {
"lat": {
"type": "number"
},
"lon": {
"type": "number"
},
"elevation_m": {
"type": "number",
"nullable": true
}
},
"required": [
"lat",
"lon",
"elevation_m"
],
"additionalProperties": true
}
}
},
"required": [
"release",
"z",
"encoding",
"points"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Point and batch weather forecast
https://trailsplits.com/api/weather/forecast· served from the main site, not the API host
Served from the main site, not the API host. Daily values per point and local date; each day names its model and issued_at is the model run (null with a reason when unknown, never the fetch time). Missing values are null, never 0; fewer days or fields than asked is state partial with reasons. Pass each point height: a model cell height can be a thousand metres off in the mountains. Attribution from provider.attribution (Open-Meteo, CC BY 4.0) is required wherever values are shown.
| Name / location | Contract |
|---|---|
p · query · required | 1–12 points as lat,lon[,elevation_m] separated by ;. Coordinates are rounded to 2 decimals (about 1 km) and echoed rounded. |
d · query | Forecast days. |
fl · query | Add the hourly freezing level. |
h · query | Add hourly[] per point over the requested days (about 130 bytes per hour and point; ask only for the days you need). Any other value is 400. |
Read the weather guide for models, heights and attribution. The downloadable examples include weather.mjs.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://trailsplits.com/api/weather/forecast?p=46.0207,7.7491,1608&d=2' {
"servers": [
{
"url": "https://trailsplits.com",
"description": "Main site; this operation is not on the API host."
}
],
"get": {
"operationId": "weather",
"summary": "Point and batch weather forecast",
"description": "Served from the main site, not the API host. Daily values per point and local date; each day names its model and issued_at is the model run (null with a reason when unknown, never the fetch time). Missing values are null, never 0; fewer days or fields than asked is state partial with reasons. Pass each point height: a model cell height can be a thousand metres off in the mountains. Attribution from provider.attribution (Open-Meteo, CC BY 4.0) is required wherever values are shown.",
"tags": [
"Developer preview"
],
"security": [],
"parameters": [
{
"name": "p",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "1–12 points as lat,lon[,elevation_m] separated by ;. Coordinates are rounded to 2 decimals (about 1 km) and echoed rounded."
},
{
"name": "d",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 16,
"default": 7
},
"description": "Forecast days."
},
{
"name": "fl",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"enum": [
1
]
},
"description": "Add the hourly freezing level."
},
{
"name": "h",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"enum": [
1
]
},
"description": "Add hourly[] per point over the requested days (about 130 bytes per hour and point; ask only for the days you need). Any other value is 400."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"503": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"weather-forecast/1"
]
},
"provider": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"model": {
"type": "string"
},
"attribution": {
"type": "string"
},
"licence": {
"type": "string"
}
},
"required": [
"attribution",
"licence"
],
"additionalProperties": true
},
"fetched_at": {
"type": "string"
},
"issued_at": {
"type": "string",
"nullable": true,
"description": "The model run, or null with issued_at_reason. Never the fetch time."
},
"issued_at_reason": {
"type": "string",
"nullable": true
},
"fresh_until": {
"type": "string"
},
"requested_days": {
"type": "integer",
"minimum": 1,
"maximum": 16
},
"points": {
"type": "array",
"minItems": 1,
"maxItems": 12,
"items": {
"$ref": "#/components/schemas/WeatherPoint"
}
}
},
"required": [
"schema",
"provider",
"fetched_at",
"issued_at",
"fresh_until",
"requested_days",
"points"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Analyse a route you already have
/v1/route-analysis
Send a GPX or GeoJSON line (at most 1 MB, 5,000 points, 300 km). The answer places it on the mapped network and says on what surface it runs, which OpenStreetMap grades are tagged, how much it climbs (method named), how long a hike takes with the model scope, and every unknown. The line you send is never rewritten, and nothing is drawn across a gap. Untagged paths are unknown, never easy. No geometry is kept after the answer.
Read the route analysis guide; the downloadable examples include analysis.mjs.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/route-analysis' \
-H 'Content-Type: application/json' \
--data '{"geometry":{"type":"LineString","coordinates":[[12.1352,46.5369],[12.133,46.536]]},"profile":"hike"}' {
"post": {
"operationId": "route-analysis",
"summary": "Analyse a route you already have",
"description": "Send a GPX or GeoJSON line (at most 1 MB, 5,000 points, 300 km). The answer places it on the mapped network and says on what surface it runs, which OpenStreetMap grades are tagged, how much it climbs (method named), how long a hike takes with the model scope, and every unknown. The line you send is never rewritten, and nothing is drawn across a gap. Untagged paths are unknown, never easy. No geometry is kept after the answer.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteAnalysisInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteAnalysis"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"413": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"route-analysis/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"profile": {
"type": "string"
},
"input": {
"type": "object",
"properties": {
"format": {
"type": "string"
},
"parts": {
"type": "integer"
},
"points": {
"type": "integer"
},
"length_m": {
"type": "number"
}
},
"required": [
"format",
"parts",
"points",
"length_m"
],
"additionalProperties": true
},
"match": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"matched",
"partial",
"unmatched"
]
},
"coverage": {
"type": "number"
},
"trace_length_m": {
"type": "number"
},
"matched_length_m": {
"type": "number"
},
"network_length_m": {
"type": "number"
},
"segments": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
"unmatched": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
},
"required": [
"status",
"coverage",
"trace_length_m",
"matched_length_m",
"network_length_m",
"segments",
"unmatched"
],
"additionalProperties": true
},
"surfaces": {
"type": "object",
"nullable": true,
"additionalProperties": true
},
"ways": {
"type": "object",
"nullable": true,
"additionalProperties": true
},
"difficulty": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Tagged sac_scale per length; untagged paths are unknown, never easy."
},
"elevation": {
"type": "object",
"nullable": true,
"additionalProperties": true
},
"time": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Hike only: trailsplits-hike/2 moving time, its scope and outside_calibration; null for run and bike."
},
"unknowns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": true
}
}
},
"required": [
"schema",
"engine",
"profile",
"input",
"match",
"unknowns"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"gpx": {
"type": "string",
"description": "A GPX 1.0/1.1 document; each trkseg (else rte) is a part. Exactly one of gpx and geometry."
},
"geometry": {
"type": "object",
"additionalProperties": true,
"description": "GeoJSON LineString, MultiLineString, a Feature of either, or a FeatureCollection of them; a third coordinate is a height."
},
"profile": {
"type": "string",
"enum": [
"hike",
"run",
"bike"
],
"default": "hike"
},
"elevation": {
"type": "string",
"enum": [
"auto",
"recorded",
"terrain"
],
"default": "auto"
}
},
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Round trips from a start point
/v1/roundtrips
Loops that start and end at a point, from the same engine as the TrailSplits Planner. Each loop reports its target error, the distance walked twice and the same facts as route analysis. Status complete means within 10 % of the target with at most 20 % repeated; rough is answered with a reason; when no good loop exists the answer is 422 no_loop, never an invented loop. Limits: 0.5–40 km on foot, 0.5–60 km by bike (422 too_long), up to 3 alternatives.
Read the round trips guide; the downloadable examples include roundtrip.mjs.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/roundtrips' \
-H 'Content-Type: application/json' \
--data '{"start":[7.7491,46.0207],"distance_km":12,"profile":"hike"}' {
"post": {
"operationId": "roundtrips",
"summary": "Round trips from a start point",
"description": "Loops that start and end at a point, from the same engine as the TrailSplits Planner. Each loop reports its target error, the distance walked twice and the same facts as route analysis. Status complete means within 10 % of the target with at most 20 % repeated; rough is answered with a reason; when no good loop exists the answer is 422 no_loop, never an invented loop. Limits: 0.5–40 km on foot, 0.5–60 km by bike (422 too_long), up to 3 alternatives.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RoundtripsInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Roundtrips"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"roundtrips/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"status": {
"type": "string",
"enum": [
"complete",
"rough"
]
},
"reason": {
"type": "string",
"nullable": true
},
"request": {
"type": "object",
"additionalProperties": true
},
"loops": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"properties": {
"rank": {
"type": "integer"
},
"status": {
"type": "string",
"enum": [
"complete",
"rough"
]
},
"distance_m": {
"type": "number"
},
"target_m": {
"type": "number"
},
"target_error_pct": {
"type": "number"
},
"repeated_m": {
"type": "number"
},
"repeated_share": {
"type": "number"
},
"shape": {
"type": "string",
"description": "Polyline6."
},
"ascent_m": {
"type": "number",
"nullable": true
},
"time": {
"type": "object",
"nullable": true,
"additionalProperties": true
}
},
"required": [
"rank",
"status",
"distance_m",
"target_m",
"target_error_pct",
"repeated_share",
"shape"
],
"additionalProperties": true
}
}
},
"required": [
"schema",
"engine",
"status",
"loops"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"start": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
"type": "number"
},
"description": "[lon, lat]"
},
"distance_km": {
"type": "number",
"minimum": 0.5,
"maximum": 60,
"description": "0.5–40 km for hike and run, to 60 km for bike. Or distance_m, not both."
},
"distance_m": {
"type": "number"
},
"profile": {
"type": "string",
"enum": [
"hike",
"run",
"bike"
],
"default": "hike"
},
"direction": {
"type": "number",
"nullable": true
},
"alternatives": {
"type": "integer",
"minimum": 0,
"maximum": 3,
"default": 0
},
"max_sac": {
"type": "integer",
"minimum": 1,
"maximum": 6,
"default": 3
},
"avoid_paved": {
"type": "boolean"
},
"hills": {
"type": "number",
"minimum": -1,
"maximum": 1
},
"bicycle_type": {
"type": "string",
"enum": [
"road",
"hybrid",
"mountain"
]
}
},
"required": [
"start"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Weather along a route at arrival time
/v1/route-weather
Send one line, a departure with its offset and a pace. Samples every 2 km plus the start, end and marked highs and lows each get the forecast at the hour you reach them, at their own terrain height, with the model named per hour. Missing stays missing (weather null with a reason). Sections give ranges, never a combined safety score. Hike uses the calibrated trailsplits-hike/2 time; run and bike need your own pace. Limits: one part, 5,000 points, 120 km, 1 MB; departure from six hours ago to 16 days ahead.
Read the route weather guide; the downloadable examples include routeweather.mjs.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/route-weather' \
-H 'Content-Type: application/json' \
--data '{"geometry":{"type":"LineString","coordinates":[[12.1352,46.5369],[12.133,46.536]]},"departure":"2026-10-03T08:00:00+02:00","profile":"hike"}'
# Set departure inside the next 16 days. {
"post": {
"operationId": "route-weather",
"summary": "Weather along a route at arrival time",
"description": "Send one line, a departure with its offset and a pace. Samples every 2 km plus the start, end and marked highs and lows each get the forecast at the hour you reach them, at their own terrain height, with the model named per hour. Missing stays missing (weather null with a reason). Sections give ranges, never a combined safety score. Hike uses the calibrated trailsplits-hike/2 time; run and bike need your own pace. Limits: one part, 5,000 points, 120 km, 1 MB; departure from six hours ago to 16 days ahead.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteWeatherInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteWeather"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"413": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"502": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"503": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"route-weather/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"departure": {
"type": "object",
"properties": {
"given": {
"type": "string"
},
"utc": {
"type": "string"
}
},
"required": [
"given",
"utc"
],
"additionalProperties": true
},
"profile": {
"type": "string"
},
"pace": {
"type": "object",
"additionalProperties": true
},
"forecast": {
"type": "object",
"properties": {
"schema": {
"type": "string"
},
"provider": {
"type": "object",
"properties": {
"attribution": {
"type": "string"
},
"licence": {
"type": "string"
}
},
"required": [
"attribution"
],
"additionalProperties": true
},
"issued_at": {
"type": "string",
"nullable": true
}
},
"required": [
"provider"
],
"additionalProperties": true
},
"samples": {
"type": "array",
"minItems": 2,
"items": {
"type": "object",
"properties": {
"at_m": {
"type": "number"
},
"kind": {
"type": "string",
"enum": [
"start",
"end",
"high",
"low",
"along"
]
},
"minutes": {
"type": "number"
},
"arrival_utc": {
"type": "string"
},
"arrival_local": {
"type": "string"
},
"forecast_elevation_m": {
"type": "number",
"nullable": true
},
"weather": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "The forecast hour reached; each hour names its model. Null with missing when the forecast does not hold it."
},
"missing": {
"type": "string",
"nullable": true
}
},
"required": [
"at_m",
"kind",
"minutes",
"arrival_utc",
"weather",
"missing"
],
"additionalProperties": true
}
},
"sections": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
"unknowns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": true
}
}
},
"required": [
"schema",
"engine",
"departure",
"forecast",
"samples",
"sections",
"unknowns"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"gpx": {
"type": "string"
},
"geometry": {
"type": "object",
"additionalProperties": true,
"description": "One part only (a LineString); as for route analysis. Limits: 5,000 points, 120 km, 1 MB."
},
"departure": {
"type": "string",
"description": "ISO 8601 with offset, from six hours ago to 16 days ahead."
},
"profile": {
"type": "string",
"enum": [
"hike",
"run",
"bike"
],
"default": "hike"
},
"pace_factor": {
"type": "number",
"minimum": 0.5,
"maximum": 2
},
"min_per_km": {
"type": "number",
"minimum": 1,
"maximum": 60
},
"kmh": {
"type": "number"
},
"stops": {
"type": "array",
"items": {
"type": "object",
"properties": {
"at_km": {
"type": "number"
},
"minutes": {
"type": "number"
}
},
"required": [
"at_km",
"minutes"
],
"additionalProperties": true
}
},
"freezing_level": {
"type": "boolean"
}
},
"required": [
"departure"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Elevation profile of a line
/v1/elevation-profile
The series a chart draws for a GPX or GeoJSON line: distance, height, grade and position at each point, as rows under named columns, with ascent, descent, extremes and the steepest stretches read from the same series (method named). Terrain heights by default, or the file's own heights when they pass the check. Each part of a file is its own run; nothing is drawn across a gap. Limits: 5,000 points, 300 km, 1 MB.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/elevation-profile' \
-H 'Content-Type: application/json' \
--data '{"geometry":{"type":"LineString","coordinates":[[12.1352,46.5369],[12.133,46.536]]},"points":50}' {
"post": {
"operationId": "elevation-profile",
"summary": "Elevation profile of a line",
"description": "The series a chart draws for a GPX or GeoJSON line: distance, height, grade and position at each point, as rows under named columns, with ascent, descent, extremes and the steepest stretches read from the same series (method named). Terrain heights by default, or the file's own heights when they pass the check. Each part of a file is its own run; nothing is drawn across a gap. Limits: 5,000 points, 300 km, 1 MB.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ElevationProfileInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ElevationProfile"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"413": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"elevation-profile/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"input": {
"type": "object",
"properties": {
"points": {
"type": "integer"
},
"length_m": {
"type": "number"
}
},
"required": [
"points",
"length_m"
],
"additionalProperties": true
},
"elevation": {
"type": "object",
"properties": {
"source": {
"type": "string",
"enum": [
"terrain",
"recorded"
]
},
"method": {
"type": "string"
},
"ascent_m": {
"type": "number"
},
"descent_m": {
"type": "number"
},
"min_m": {
"type": "number"
},
"max_m": {
"type": "number"
}
},
"required": [
"source",
"method",
"ascent_m",
"descent_m"
],
"additionalProperties": true
},
"series": {
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"description": "distance_m, elevation_m, grade_pct, lon, lat"
},
"heights": {
"type": "string"
},
"parts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"from_m": {
"type": "number"
},
"to_m": {
"type": "number"
},
"first": {
"type": "integer"
},
"last": {
"type": "integer"
}
},
"required": [
"from_m",
"to_m",
"first",
"last"
],
"additionalProperties": true
}
},
"points": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "number",
"nullable": true
}
}
}
},
"required": [
"columns",
"parts",
"points"
],
"additionalProperties": true
},
"unknowns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": true
}
}
},
"required": [
"schema",
"engine",
"input",
"elevation",
"series",
"unknowns"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"gpx": {
"type": "string"
},
"geometry": {
"type": "object",
"additionalProperties": true,
"description": "A GeoJSON line, as for route analysis. Limits: 5,000 points, 300 km, 1 MB."
},
"elevation": {
"type": "string",
"enum": [
"auto",
"recorded",
"terrain"
],
"default": "auto"
},
"points": {
"type": "integer",
"minimum": 2,
"maximum": 6000,
"default": 1000,
"description": "At most this many points in the series."
}
},
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Route through waypoints
/v1/route
A walking, running or cycling route through 2 to 100 waypoints, on signed trails by default. Returns the route as a GeoJSON line with its legs and the same facts as round trips and route analysis: climb, the hike time with its scope, surfaces, ways, SAC grades, fords and aided passages, turn-by-turn steps and every unknown. The same router as the Valhalla-compatible POST /route/v1, in the /v1 style: [lon, lat] waypoints, flat snake_case settings, errors as { error: { code, message } }. Credits as /route/v1: 1, plus 1 per further 10 waypoints.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/route' \
-H 'Content-Type: application/json' \
--data '{"waypoints":[[7.7475,46.0207],[7.7174,46.0091],[7.7355,46.0036]]}' {
"post": {
"operationId": "waypoint-route",
"summary": "Route through waypoints",
"description": "A walking, running or cycling route through 2 to 100 waypoints, on signed trails by default. Returns the route as a GeoJSON line with its legs and the same facts as round trips and route analysis: climb, the hike time with its scope, surfaces, ways, SAC grades, fords and aided passages, turn-by-turn steps and every unknown. The same router as the Valhalla-compatible POST /route/v1, in the /v1 style: [lon, lat] waypoints, flat snake_case settings, errors as { error: { code, message } }. Credits as /route/v1: 1, plus 1 per further 10 waypoints.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WaypointRouteInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WaypointRoute"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"413": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"503": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"route/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"status": {
"type": "string",
"enum": [
"complete",
"best_effort"
],
"description": "complete: every leg is a proven cheapest path under the settings. best_effort: a leg hit the search budget (a warning says which)."
},
"settings": {
"type": "object",
"additionalProperties": true,
"description": "What was applied, in the request’s words."
},
"settings_defaulted": {
"type": "array",
"items": {
"type": "string"
}
},
"distance_m": {
"type": "number"
},
"ascent_m": {
"type": "number"
},
"descent_m": {
"type": "number"
},
"ascent_method": {
"type": "string"
},
"time": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Hike only: moving time from the calibrated trailsplits-hike/2 model, with its scope and error. Null for run and bike."
},
"surfaces": {
"type": "object",
"additionalProperties": true,
"description": "Paved, gravel, trail and unknown metres; mapped or assumed from the kind of way; stretches placed along the route."
},
"hazards": {
"type": "array",
"items": {
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [
"ford",
"aid",
"via_ferrata"
]
},
"from_m": {
"type": "number"
},
"to_m": {
"type": "number"
},
"length_m": {
"type": "number"
},
"way_id": {
"type": "number",
"nullable": true
}
},
"required": [
"kind",
"from_m",
"to_m",
"length_m",
"way_id"
],
"additionalProperties": true
}
},
"ways": {
"type": "object",
"additionalProperties": true
},
"difficulty": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "SAC-tagged metres by grade, untagged path and road metres, and the hardest stretch."
},
"warnings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"location": {
"type": "array",
"items": {
"type": "number"
},
"nullable": true
}
},
"required": [
"code",
"message",
"location"
],
"additionalProperties": true
}
},
"unknowns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": true
}
},
"geometry": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"LineString"
]
},
"coordinates": {
"type": "array",
"minItems": 2,
"items": {
"type": "array",
"items": {
"type": "number"
}
},
"description": "[lon, lat, height]"
}
},
"required": [
"type",
"coordinates"
],
"additionalProperties": true
},
"legs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"leg": {
"type": "integer"
},
"distance_m": {
"type": "number"
},
"ascent_m": {
"type": "number"
},
"descent_m": {
"type": "number"
},
"from_snap_m": {
"type": "number"
},
"to_snap_m": {
"type": "number"
}
},
"required": [
"leg",
"distance_m",
"ascent_m",
"descent_m",
"from_snap_m",
"to_snap_m"
],
"additionalProperties": true
}
},
"snaps": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
"maneuvers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"instruction": {
"type": "string"
},
"type": {
"type": "string"
},
"location": {
"type": "array",
"items": {
"type": "number"
}
},
"distance_m": {
"type": "number"
}
},
"required": [
"instruction",
"type",
"location",
"distance_m"
],
"additionalProperties": true
}
},
"cap_alternative": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "When the grade cap was left at its default and a harder path is much shorter: its max_sac, distance, climb and minutes."
}
},
"required": [
"schema",
"engine",
"status",
"settings",
"distance_m",
"ascent_m",
"descent_m",
"time",
"surfaces",
"hazards",
"warnings",
"unknowns",
"geometry",
"legs",
"maneuvers"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"waypoints": {
"type": "array",
"minItems": 2,
"maxItems": 100,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": {
"type": "number"
}
},
"description": "2 to 100 points, [lon, lat]. A leg (between two waypoints) may be at most 100 km in a straight line."
},
"profile": {
"type": "string",
"enum": [
"hike",
"run",
"bike"
],
"default": "hike"
},
"max_sac": {
"type": "integer",
"minimum": 1,
"maximum": 6,
"default": 3,
"description": "Hike and run: the hardest SAC grade allowed, 1 (T1) to 6 (T6). Refused for a bike."
},
"marked_trails": {
"type": "string",
"enum": [
"strict",
"prefer",
"off"
],
"default": "prefer",
"description": "Hike and run: how strongly to keep to waymarked trails. Bikes: off."
},
"avoid_paved": {
"type": "boolean",
"default": false
},
"hills": {
"type": "number",
"minimum": -1,
"maximum": 1,
"default": 0,
"description": "From -1 (avoid climbing) to 1 (seek it)."
},
"shortest": {
"type": "boolean",
"default": false,
"description": "The shortest route under the other settings, not the most suitable."
},
"bicycle_type": {
"type": "string",
"enum": [
"road",
"hybrid",
"mountain"
],
"description": "Bike only."
},
"straight_legs": {
"type": "array",
"items": {
"type": "integer"
},
"description": "Leg numbers (0 joins the first waypoint to the second) to draw straight, on no mapped path."
},
"snap_radius_m": {
"type": "number",
"minimum": 10,
"maximum": 5000,
"description": "How far a waypoint may lie from a usable path."
}
},
"required": [
"waypoints"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Clean a GPX file
/v1/gpx/clean
Removes repeated points and points with broken coordinates, and optionally every time stamp and sensor extension (heart rate, cadence, power). The file comes back as the file: only what was removed is cut; names, comments, CDATA, waypoints and indentation stay byte for byte. A report says what changed. Body at most 5 MB, 50,000 points.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/gpx/clean' \
-H 'Content-Type: application/json' \
--data '{"gpx":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><gpx version=\"1.1\" creator=\"example\" xmlns=\"http://www.topografix.com/GPX/1/1\"><trk><name>Example</name><trkseg><trkpt lat=\"46.5369\" lon=\"12.1352\"><ele>1183</ele></trkpt><trkpt lat=\"46.5369\" lon=\"12.1352\"><ele>1183</ele></trkpt><trkpt lat=\"46.5365\" lon=\"12.1341\"><ele>1190</ele></trkpt><trkpt lat=\"46.5360\" lon=\"12.1330\"><ele>1195</ele></trkpt></trkseg></trk></gpx>"}' {
"post": {
"operationId": "gpx-clean",
"summary": "Clean a GPX file",
"description": "Removes repeated points and points with broken coordinates, and optionally every time stamp and sensor extension (heart rate, cadence, power). The file comes back as the file: only what was removed is cut; names, comments, CDATA, waypoints and indentation stay byte for byte. A report says what changed. Body at most 5 MB, 50,000 points.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GpxCleanInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GpxClean"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"413": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"gpx-clean/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"settings": {
"type": "object",
"additionalProperties": true
},
"report": {
"type": "object",
"properties": {
"changed": {
"type": "boolean"
},
"points_before": {
"type": "integer"
},
"points_after": {
"type": "integer"
},
"duplicates": {
"type": "integer"
},
"bad_coordinates": {
"type": "integer"
}
},
"required": [
"changed",
"points_before",
"points_after"
],
"additionalProperties": true
},
"gpx": {
"type": "string",
"description": "The cleaned file; byte for byte the input where nothing was removed."
}
},
"required": [
"schema",
"report",
"gpx"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"gpx": {
"type": "string",
"description": "The GPX document. Body at most 5 MB, 50,000 points."
},
"dedupe": {
"type": "boolean",
"default": true
},
"drop_bad": {
"type": "boolean",
"default": true
},
"strip_times": {
"type": "boolean",
"default": false
},
"strip_extensions": {
"type": "boolean",
"default": false
}
},
"required": [
"gpx"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Simplify a GPX file or line
/v1/gpx/simplify
Fewer points with the shape kept within a tolerance in ground metres (or a point budget), the climb protected and stops (waypoints, pauses of 10 minutes or more) kept in place. Reports the largest deviation and the distance and climb before and after. Answers equal the TrailSplits GPX Simplifier. Body at most 5 MB, 50,000 points.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/v1/gpx/simplify' \
-H 'Content-Type: application/json' \
--data '{"geometry":{"type":"LineString","coordinates":[[12.1352,46.5369],[12.13509,46.536875],[12.13498,46.53681],[12.13487,46.536785],[12.13476,46.53672],[12.13465,46.536695],[12.13454,46.53663],[12.13443,46.536605],[12.13432,46.53654],[12.13421,46.536515],[12.1341,46.53645],[12.13399,46.536425],[12.13388,46.53636],[12.13377,46.536335],[12.13366,46.53627],[12.13355,46.536245],[12.13344,46.53618],[12.13333,46.536155],[12.13322,46.53609],[12.13311,46.536065],[12.133,46.536]]},"tolerance_m":10}' {
"post": {
"operationId": "gpx-simplify",
"summary": "Simplify a GPX file or line",
"description": "Fewer points with the shape kept within a tolerance in ground metres (or a point budget), the climb protected and stops (waypoints, pauses of 10 minutes or more) kept in place. Reports the largest deviation and the distance and climb before and after. Answers equal the TrailSplits GPX Simplifier. Body at most 5 MB, 50,000 points.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GpxSimplifyInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GpxSimplify"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"413": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProductError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"gpx-simplify/1"
]
},
"engine": {
"type": "object",
"additionalProperties": true
},
"settings": {
"type": "object",
"additionalProperties": true
},
"input": {
"type": "object",
"properties": {
"format": {
"type": "string"
},
"segments": {
"type": "integer"
},
"points": {
"type": "integer"
}
},
"required": [
"format",
"segments",
"points"
],
"additionalProperties": true
},
"result": {
"type": "object",
"properties": {
"points": {
"type": "integer"
},
"removed": {
"type": "integer"
},
"max_deviation_m": {
"type": "number",
"nullable": true
}
},
"required": [
"points",
"removed"
],
"additionalProperties": true
},
"gpx": {
"type": "string"
},
"geometry": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"schema",
"input",
"result"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"gpx": {
"type": "string"
},
"geometry": {
"type": "object",
"additionalProperties": true
},
"tolerance_m": {
"type": "number",
"minimum": 0.5,
"maximum": 1000,
"default": 10
},
"max_points": {
"type": "integer",
"description": "Budget mode instead of tolerance_m."
},
"keep_climb": {
"type": "boolean",
"default": true
},
"keep_stops": {
"type": "boolean",
"default": true
},
"indices": {
"type": "boolean",
"default": false
}
},
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Place search
/search/v1/forward
Places and signed trails by name: towns, peaks, passes, lakes, huts, stations and more. A bias_bbox lifts places in the map view without excluding others. Misspellings and German ue/oe/ae spellings are found when nothing matches exactly (match: fuzzy). Coordinates are [lon, lat]. Not an address geocoder.
| Name / location | Contract |
|---|---|
q · query · required | The name, at least 2 letters. "Name, Place" searches near that place; "Place station" finds its railway stations. |
limit · query | Results. |
bias_bbox · query | minLon,minLat,maxLon,maxLat: a soft preference for the map view. |
bbox · query | minLon,minLat,maxLon,maxLat: a hard filter. |
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/search/v1/forward?q=Matterhorn&limit=3&bias_bbox=7.5,45.9,7.9,46.1' {
"get": {
"operationId": "search",
"summary": "Place search",
"description": "Places and signed trails by name: towns, peaks, passes, lakes, huts, stations and more. A bias_bbox lifts places in the map view without excluding others. Misspellings and German ue/oe/ae spellings are found when nothing matches exactly (match: fuzzy). Coordinates are [lon, lat]. Not an address geocoder.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [
{
"name": "q",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "The name, at least 2 letters. \"Name, Place\" searches near that place; \"Place station\" finds its railway stations."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"default": 10
},
"description": "Results."
},
{
"name": "bias_bbox",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "minLon,minLat,maxLon,maxLat: a soft preference for the map view."
},
{
"name": "bbox",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "minLon,minLat,maxLon,maxLat: a hard filter."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchResult"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"query": {
"type": "string"
},
"features": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Place"
}
}
},
"required": [
"query",
"features"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Places near a point
/search/v1/reverse
The nearest named places to a point, nearest first, with their distance in metres. Narrow to kinds (for example peak,hut,village) and widen the radius up to 50 km.
| Name / location | Contract |
|---|---|
lat · query · required | Latitude. |
lon · query · required | Longitude. |
limit · query | Results. |
radius_m · query | Search radius in metres. |
kinds · query | Comma-separated kinds to keep. |
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/search/v1/reverse?lat=46.0207&lon=7.7491&limit=3' {
"get": {
"operationId": "reverse",
"summary": "Places near a point",
"description": "The nearest named places to a point, nearest first, with their distance in metres. Narrow to kinds (for example peak,hut,village) and widen the radius up to 50 km.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [
{
"name": "lat",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "Latitude."
},
{
"name": "lon",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "Longitude."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"default": 10
},
"description": "Results."
},
{
"name": "radius_m",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 50,
"maximum": 50000,
"default": 500
},
"description": "Search radius in metres."
},
{
"name": "kinds",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Comma-separated kinds to keep."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReverseResult"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"lat": {
"type": "number"
},
"lon": {
"type": "number"
},
"radius_m": {
"type": "number"
},
"features": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"kind": {
"type": "string"
},
"center": {
"type": "array",
"items": {
"type": "number"
}
},
"distance_m": {
"type": "number"
},
"region": {
"type": "string",
"nullable": true
}
},
"required": [
"id",
"name",
"kind",
"center",
"distance_m"
],
"additionalProperties": true
}
}
},
"required": [
"lat",
"lon",
"radius_m",
"features"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Trail search
/trails/v1/search
Signed hiking and cycling routes (OpenStreetMap route relations) by name or reference, with network level, length and bounding box; the geometry is a representative point. Fetch a relation's full line with GET /trails/v1/relation/{osm_id}, or relations in an area with /trails/v1/bbox.
| Name / location | Contract |
|---|---|
q · query · required | Name or reference. |
limit · query | Results. |
type · query | Route type. |
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/trails/v1/search?q=Haute+Route&limit=3' {
"get": {
"operationId": "trails",
"summary": "Trail search",
"description": "Signed hiking and cycling routes (OpenStreetMap route relations) by name or reference, with network level, length and bounding box; the geometry is a representative point. Fetch a relation's full line with GET /trails/v1/relation/{osm_id}, or relations in an area with /trails/v1/bbox.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [
{
"name": "q",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "Name or reference."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"description": "Results."
},
{
"name": "type",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": [
"hiking",
"bicycle"
]
},
"description": "Route type."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TrailSearchResult"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"FeatureCollection"
]
},
"query": {
"type": "string"
},
"features": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"Feature"
]
},
"properties": {
"type": "object",
"properties": {
"osm_relation_id": {
"type": "integer"
},
"route_type": {
"type": "string"
},
"name": {
"type": "string"
},
"network": {
"type": "string",
"nullable": true
},
"distance_m": {
"type": "number"
},
"bbox": {
"type": "array",
"items": {
"type": "number"
}
}
},
"required": [
"osm_relation_id",
"name"
],
"additionalProperties": true
},
"geometry": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": {
"type": "number"
}
}
},
"required": [
"type",
"coordinates"
],
"additionalProperties": true
}
},
"required": [
"type",
"properties",
"geometry"
],
"additionalProperties": true
}
}
},
"required": [
"type",
"query",
"features"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Outdoor places in an area
/pois/v1/bbox
Huts, shelters, water, viewpoints, passes, parking and transport stops in a small box, as flat records (lat, lon, ele and OSM tags), not GeoJSON Features. Each side of the box may be at most 2°. artifact_version names the weekly release used.
| Name / location | Contract |
|---|---|
min_lat · query · required | South. |
min_lon · query · required | West. |
max_lat · query · required | North. |
max_lon · query · required | East. |
kind · query | Comma-separated kinds, for example hut,shelter,drinking_water. |
limit · query | Records. |
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/pois/v1/bbox?min_lat=46&min_lon=7.7&max_lat=46.05&max_lon=7.8&kind=hut&limit=5' {
"get": {
"operationId": "pois",
"summary": "Outdoor places in an area",
"description": "Huts, shelters, water, viewpoints, passes, parking and transport stops in a small box, as flat records (lat, lon, ele and OSM tags), not GeoJSON Features. Each side of the box may be at most 2°. artifact_version names the weekly release used.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [
{
"name": "min_lat",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "South."
},
{
"name": "min_lon",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "West."
},
{
"name": "max_lat",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "North."
},
{
"name": "max_lon",
"in": "query",
"required": true,
"schema": {
"type": "number"
},
"description": "East."
},
{
"name": "kind",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Comma-separated kinds, for example hut,shelter,drinking_water."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 10000,
"default": 2000
},
"description": "Records."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PoiBboxResult"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"FeatureCollection"
]
},
"count": {
"type": "integer"
},
"artifact_version": {
"type": "string"
},
"features": {
"type": "array",
"items": {
"type": "object",
"properties": {
"kind": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
},
"ele": {
"type": "number",
"nullable": true
},
"lat": {
"type": "number"
},
"lon": {
"type": "number"
},
"osm_id": {
"type": "string",
"nullable": true
},
"tags": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"kind",
"lat",
"lon"
],
"additionalProperties": true
}
}
},
"required": [
"type",
"features"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Static map image
/static-map/render
A PNG of the outdoor map for a box, with an optional GeoJSON line or features drawn on it: for cards, emails and print. Attribution is drawn into the image; keep it visible.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/static-map/render' \
-H 'Content-Type: application/json' \
--data '{"bbox":[12.13,46.535,12.137,46.538],"width":320,"height":200}' \
-o map.png {
"post": {
"operationId": "static-map",
"summary": "Static map image",
"description": "A PNG of the outdoor map for a box, with an optional GeoJSON line or features drawn on it: for cards, emails and print. Attribution is drawn into the image; keep it visible.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/StaticMapInput"
}
}
}
},
"responses": {
"200": {
"description": "PNG image.",
"content": {
"image/png": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"503": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"bbox": {
"type": "array",
"minItems": 4,
"maxItems": 4,
"items": {
"type": "number"
},
"description": "[minLon, minLat, maxLon, maxLat]"
},
"width": {
"type": "integer",
"minimum": 1,
"maximum": 2000
},
"height": {
"type": "integer",
"minimum": 1,
"maximum": 2000
},
"geojson": {
"type": "object",
"additionalProperties": true
},
"padding": {
"type": "number"
}
},
"required": [
"bbox"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Map matching and trace attributes
/valhalla/trace_attributes
Matches a line to the mapped network and returns each way it follows with surface (and whether the surface is mapped or a class default), use and SAC grade, plus the matched line per segment, unmatched stretches with reasons, and three lengths. Valhalla-compatible input; up to 2,000 points. Edge lengths are kilometres. For a full analysis with climb, time and unknowns use route analysis.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/valhalla/trace_attributes' \
-H 'Content-Type: application/json' \
--data '{"shape":[{"lat":46.5369,"lon":12.1352},{"lat":46.536,"lon":12.133}],"costing":"pedestrian","shape_match":"map_snap"}' {
"post": {
"operationId": "trace-attributes",
"summary": "Map matching and trace attributes",
"description": "Matches a line to the mapped network and returns each way it follows with surface (and whether the surface is mapped or a class default), use and SAC grade, plus the matched line per segment, unmatched stretches with reasons, and three lengths. Valhalla-compatible input; up to 2,000 points. Edge lengths are kilometres. For a full analysis with climb, time and unknowns use route analysis.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TraceAttributesInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TraceAttributes"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"type": "object",
"properties": {
"length": {
"type": "number",
"description": "Kilometres."
},
"begin_shape_index": {
"type": "integer"
},
"end_shape_index": {
"type": "integer"
},
"surface": {
"type": "string",
"nullable": true
},
"trailsplits_surface_tagged": {
"type": "boolean"
},
"use": {
"type": "string",
"nullable": true
},
"sac_scale": {
"type": "integer",
"nullable": true
}
},
"required": [
"length"
],
"additionalProperties": true
}
},
"shape": {
"type": "string",
"description": "Polyline6 of the matched line, only when the match is one segment."
},
"units": {
"type": "string",
"enum": [
"kilometers"
]
},
"trailsplits": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"matched",
"partial",
"unmatched"
]
},
"coverage": {
"type": "number"
},
"trace_length_m": {
"type": "number"
},
"matched_length_m": {
"type": "number"
},
"segments": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
"unmatched": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
},
"required": [
"status",
"coverage",
"segments"
],
"additionalProperties": true
}
},
"required": [
"edges",
"trailsplits"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"shape": {
"type": "array",
"minItems": 2,
"maxItems": 2000,
"items": {
"type": "object",
"properties": {
"lat": {
"type": "number"
},
"lon": {
"type": "number"
}
},
"required": [
"lat",
"lon"
],
"additionalProperties": true
}
},
"costing": {
"type": "string",
"enum": [
"pedestrian",
"bicycle"
]
},
"shape_match": {
"type": "string",
"enum": [
"map_snap"
]
}
},
"required": [
"shape",
"costing"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
GET
Snow along a route
/tiles/v1/snow/route-forecast
Observed and recent snow cover at up to 512 sampled points, with 24 h and 48 h forecasts kept apart. With evidence=1 the answer carries route-snow-evidence/1: per-point class (snow, clear, unknown) and source, coverage, and a short validity. Unknown is never clear; narrow crossings between samples are not assessed. Points are lat,lon.
| Name / location | Contract |
|---|---|
points · query · required | lat,lon pairs separated by |, at most 512. |
evidence · query | Add the route-snow-evidence/1 block. |
revision · query | Your geometry version, echoed back (1–64 letters, digits or ._:-). |
segments · query | Start indices of disconnected segments. |
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/tiles/v1/snow/route-forecast?points=46.0207,7.7491%7C46,7.7&evidence=1&revision=example1' {
"get": {
"operationId": "snow",
"summary": "Snow along a route",
"description": "Observed and recent snow cover at up to 512 sampled points, with 24 h and 48 h forecasts kept apart. With evidence=1 the answer carries route-snow-evidence/1: per-point class (snow, clear, unknown) and source, coverage, and a short validity. Unknown is never clear; narrow crossings between samples are not assessed. Points are lat,lon.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [
{
"name": "points",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "lat,lon pairs separated by |, at most 512."
},
{
"name": "evidence",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"enum": [
1
]
},
"description": "Add the route-snow-evidence/1 block."
},
{
"name": "revision",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Your geometry version, echoed back (1–64 letters, digits or ._:-)."
},
{
"name": "segments",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Start indices of disconnected segments."
}
],
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SnowRoute"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"503": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"evidence": {
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"route-snow-evidence/1"
]
},
"revision": {
"type": "string"
},
"valid_for": {
"type": "string"
},
"sampling": {
"type": "object",
"properties": {
"points": {
"type": "integer"
}
},
"required": [
"points"
],
"additionalProperties": true
},
"summary": {
"type": "object",
"properties": {
"percent_snow": {
"type": "number"
},
"percent_clear": {
"type": "number"
},
"percent_unknown": {
"type": "number"
},
"coverage": {
"type": "string",
"enum": [
"full",
"partial",
"none"
]
}
},
"required": [
"percent_snow",
"percent_clear",
"percent_unknown",
"coverage"
],
"additionalProperties": true
},
"points": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
},
"required": [
"schema",
"revision",
"sampling",
"summary",
"points"
],
"additionalProperties": true
},
"forecast_24h": {
"type": "object",
"additionalProperties": true
},
"forecast_48h": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"evidence"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
POST
Outdoor point-to-point route
/route/v1
Verified POST integration subset of Valhalla-compatible input; returns OSRM-shaped output with polyline6, metres and estimated seconds. Walking explicitly sets T3; running uses trailsplits.profile=run, cycling uses bicycle/hybrid. Unsupported car costing returns 400. No failure should become a straight-line route. Engine/settings and tile release are returned provenance, not immutable route replay. The Planner has a different site body/defaults; read /api/route/capabilities on trailsplits.com.
Run the outdoor routing example to inspect a live result or refusal.
Full reference, examples in curl, JavaScript and Python, and Try it →
Inspect request and response shapes
curl --fail-with-body 'https://api.trailsplits.com/route/v1' \
-H 'Content-Type: application/json' \
--data '{"locations":[{"lat":46.5369,"lon":12.1352},{"lat":46.536,"lon":12.133}],"costing":"pedestrian","costing_options":{"pedestrian":{"max_hiking_difficulty":3}}}' {
"post": {
"operationId": "route",
"summary": "Outdoor point-to-point route",
"description": "Verified POST integration subset of Valhalla-compatible input; returns OSRM-shaped output with polyline6, metres and estimated seconds. Walking explicitly sets T3; running uses trailsplits.profile=run, cycling uses bicycle/hybrid. Unsupported car costing returns 400. No failure should become a straight-line route. Engine/settings and tile release are returned provenance, not immutable route replay. The Planner has a different site body/defaults; read /api/route/capabilities on trailsplits.com.",
"tags": [
"Developer preview"
],
"security": [
{},
{
"ApiKey": []
}
],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteInput"
}
}
}
},
"responses": {
"200": {
"description": "Successful response; additive fields are allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Route"
}
}
}
},
"400": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteError"
}
}
}
},
"422": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteError"
}
}
}
},
"503": {
"description": "Documented error/refusal; no result geometry should be fabricated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RouteError"
}
}
}
},
"default": {
"description": "Other gateway/provider failures are possible in preview. Consumers bound and surface them; do not treat an unknown status as success."
}
}
}
} {
"type": "object",
"properties": {
"code": {
"type": "string",
"enum": [
"Ok"
]
},
"routes": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"geometry": {
"type": "string",
"minLength": 1,
"description": "Polyline6; decoding yields lon,lat GeoJSON positions."
},
"distance": {
"type": "number",
"minimum": 0,
"description": "Metres."
},
"duration": {
"type": "number",
"minimum": 0,
"description": "Estimated seconds."
}
},
"required": [
"geometry",
"distance",
"duration"
],
"additionalProperties": true
}
},
"trailsplits": {
"type": "object",
"properties": {
"engine": {
"type": "object",
"nullable": true,
"additionalProperties": true,
"description": "Available engine/tile/settings provenance; absent is unknown. Not a pinning parameter."
},
"warnings": {
"type": "array",
"items": {}
},
"summary": {
"type": "object",
"nullable": true,
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"required": [
"code",
"routes"
],
"additionalProperties": true
} {
"type": "object",
"properties": {
"locations": {
"type": "array",
"minItems": 2,
"maxItems": 100,
"items": {
"type": "object",
"properties": {
"lat": {
"type": "number",
"minimum": -85.05,
"maximum": 85.05
},
"lon": {
"type": "number",
"minimum": -180,
"maximum": 180
}
},
"required": [
"lat",
"lon"
],
"additionalProperties": true
}
},
"costing": {
"type": "string",
"enum": [
"pedestrian",
"bicycle",
"auto"
],
"description": "auto is included only to document its HTTP 400 refusal."
},
"trailsplits": {
"type": "object",
"properties": {
"profile": {
"type": "string",
"enum": [
"run"
]
}
},
"required": [
"profile"
],
"additionalProperties": true
},
"costing_options": {
"type": "object",
"properties": {
"pedestrian": {
"type": "object",
"properties": {
"max_hiking_difficulty": {
"type": "integer",
"minimum": 1,
"maximum": 6
}
},
"required": [
"max_hiking_difficulty"
],
"additionalProperties": true
},
"bicycle": {
"type": "object",
"properties": {
"bicycle_type": {
"type": "string",
"enum": [
"hybrid"
]
},
"use_roads": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"use_ferry": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"bicycle_type",
"use_roads",
"use_ferry"
],
"additionalProperties": true
}
},
"additionalProperties": true
}
},
"required": [
"locations",
"costing"
],
"additionalProperties": true
} Schema references resolve in the downloadable OpenAPI file. A shape check does not establish field accuracy or physical route suitability.
Binary delivery has separate semantics
MapLibre consumes the published style and glyphs, vector tiles within PMTiles, and Mapbox-encoded TerrainRGB PNG tiles. The JSON reference deliberately does not pretend these are ordinary record APIs.
- Resolve basemap, style and terrain independently from the manifest. Replace mutable style dependencies with compatible versioned addresses. Source dates can be null; promotion dates are different from source dates.
- PMTiles v3 needs HTTP Range. The map example requires 206 and the exact requested length, cancelling a 200 whole-archive response. A 1,024-byte signature probe checks transport only; it does not validate the full archive or rendered map.
- The fixed-view map is bounded to 128 assets / 16 MiB, 2 MiB per response plus two 256 KiB JSON requests. Terrain uses native z12 in the tested release and 1.2× visual exaggeration. More pixels or overzoom create no extra source detail.
- The current style has no sprite-dependent layers. Its unused placeholder failed browser decoding on 2 October and is omitted explicitly by the example; a future sprite-dependent style must load valid pinned assets.
- Keep the existing source-specific credits visible. Retained versions can retire, and public availability does not authorize every redistribution use.
Run the rendered map and inspect its actual artifact evidence. The terrain reference and basemap reference retain the fuller technical details.
How these are checked
Each operation on this page has a live probe: a fixed example request whose answer is checked for shape, units and meaning, not only for HTTP 200. The checks are bounded (a few small serial requests, no retries) and run after every release of the docs. A failing check keeps the operation out of this list until it passes again.