Places along a route
POST https://api.trailsplits.com/v1/route-places
Checked by a live probe Key optional · 500 credits a day without one Daily area ceiling: 3,000 on Free
Mapped drinking water, springs, huts, shelters and transport stops near a GPX or GeoJSON line, in order along it, each with metres along and off the line, its OSM tags exactly as tagged, and the longest stretch without mapped water. It says where water is mapped in OpenStreetMap, never that it runs: a tap may be off and a spring dry. Credits: 1 per started 25 km of line; each call also counts once toward the daily area ceiling.
Example
# Without a key, leave out the Authorization line (500 credits a day per address).
curl --fail-with-body 'https://api.trailsplits.com/v1/route-places' \
-H "Authorization: Bearer $TRAILSPLITS_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"geometry":{"type":"LineString","coordinates":[[6.97178,45.79266],[6.98409,45.80185],[6.98629,45.80488],[6.98231,45.80634],[6.9782,45.80782],[6.9784,45.81286],[6.98961,45.82424],[7.00303,45.82901],[7.0139,45.83525],[7.02084,45.83669],[7.02859,45.84621],[7.03402,45.84664]]},"within_m":300}' Request body
| Field | Type | Description |
|---|---|---|
gpx | string | One line as GPX (several parts allowed; distances skip the gaps). Or geometry, not both. Limits: 5,000 points, 300 km, 1 MB. |
geometry | object | A GeoJSON LineString or MultiLineString, [lon, lat]. |
kinds | array | Default all. |
within_m | number | How far from the line a place may lie. |
Response
| Field | Type | Description |
|---|---|---|
schema | string: route-places/1 | |
engine | object | |
settings | object | |
settings_defaulted | array | |
input | object | |
source | object | |
places | array | |
counts | object | |
water | object or null | When water or springs are asked: how many are mapped, and the longest stretches without mapped water (and without water not tagged seasonal, intermittent or drinking_water=no). |
unknowns | array |
Full response schema (JSON Schema)
{
"type": "object",
"properties": {
"schema": {
"type": "string",
"enum": [
"route-places/1"
]
},
"engine": {
"type": "object"
},
"settings": {
"type": "object"
},
"settings_defaulted": {
"type": "array",
"items": {
"type": "string"
}
},
"input": {
"type": "object",
"properties": {
"format": {
"type": "string"
},
"parts": {
"type": "integer"
},
"points": {
"type": "integer"
},
"length_m": {
"type": "number"
},
"gaps_m": {
"type": "array",
"items": {
"type": "number"
}
}
},
"required": [
"length_m"
]
},
"source": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"licence": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"name",
"licence",
"version"
]
},
"places": {
"type": "array",
"items": {
"type": "object",
"properties": {
"at_m": {
"type": "number",
"description": "Along the line."
},
"offset_m": {
"type": "number",
"description": "Off the line."
},
"category": {
"type": "string",
"enum": [
"water",
"spring",
"hut",
"shelter",
"transport"
]
},
"kind": {
"type": "string"
},
"name": {
"type": "string",
"nullable": true
},
"lon": {
"type": "number"
},
"lat": {
"type": "number"
},
"ele_m": {
"type": "number",
"nullable": true
},
"osm_id": {
"type": "string"
},
"osm_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"tags": {
"type": "object",
"additionalProperties": true,
"description": "Exactly as tagged."
}
},
"required": [
"at_m",
"offset_m",
"category",
"kind",
"lon",
"lat",
"osm_ids",
"tags"
]
}
},
"counts": {
"type": "object"
},
"water": {
"type": "object",
"nullable": true,
"description": "When water or springs are asked: how many are mapped, and the longest stretches without mapped water (and without water not tagged seasonal, intermittent or drinking_water=no)."
},
"unknowns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
]
}
}
},
"required": [
"schema",
"engine",
"input",
"source",
"places",
"counts",
"water",
"unknowns"
]
}Errors
400, 413, 422, 503, plus the gateway's 401, 429 and 503 (error conventions). A refused request costs no credits.
Contract
Mapped drinking water, springs, huts, shelters and transport stops near a line. Each is placed in metres along it, with how far off the line it lies. The answer also gives the longest stretch without mapped water.
What it says, and what it does not.
-
What OpenStreetMap maps. Everything comes from TrailSplits' weekly places index (OSM, ODbL). Tags are given exactly as tagged: a fountain tagged
seasonal=summeror a spring taggedintermittent=yessays so, and nothing more. - Mapped, not running. A tap may be turned off and a spring may be dry. This says where water is mapped, never that it runs.
- No safety claims. No "carry enough water" or similar advice: apps decide what to make of a long stretch without mapped water.
Request
{ "gpx": "<gpx…>" }
{ "geometry": { "type": "LineString", "coordinates": [[lon, lat], …] }, "kinds": ["water", "spring", "hut"], "within_m": 300 }
| Field | Default | |
|---|---|---|
gpx or geometry | one of them | As for route analysis: 5,000 points, 300 km, 1 MB; several parts are allowed, and distances skip the gaps between them |
kinds | all | Any of water (amenity=drinking_water or fountain), spring (natural=spring), hut (alpine and wilderness huts), shelter, transport (stations, bus, tram and ferry stops, lift stations) |
within_m | 100 | How far from the line a place may lie, 10 to 1,000 m |
caller | Optional label |
Response
| Field | Meaning |
|---|---|
schema | route-places/1 |
settings, settings_defaulted | kinds and within_m as used |
input | format, parts, points, length_m (gaps excluded), gaps_m |
source | name, licence (ODbL, © OpenStreetMap contributors) and version: the weekly build read, such as osm_weekly_20260928_0312 |
places[] | In order along the line. Each has at_m (along the line) and offset_m (off it); category (water, spring, hut, shelter, transport) and the index's kind (such as bus_stop or cable_car); name, lon, lat and ele_m (as mapped); osm_id; and tags exactly as stored. Water and springs also carry seasonal, intermittent and drinking_water straight from their tags, null where untagged |
osm_ids | One place is often mapped several times, such as a stop's positions and platforms for each direction. The same kind and name within 150 m along the line (stops on either side of a junction) is one place, at the mapping nearest the line, and osm_ids lists every OSM id |
counts | Places per asked category |
water | When water or springs are asked (else null): mapped (how many), longest_without_mapped_water and longest_without_untagged_water (counting only water not tagged seasonal, intermittent or drinking_water=no), each with from_m, to_m and length_m (the line's start and end count as ends of a stretch), and a note in words |
unknowns[] | code, message: springs_not_indexed and water_tags_not_indexed while the index read predates the weekly build of 4 October 2026 (the absence is not a fact then), and places_truncated when a stretch holds more than 2,000 places nearby |
timing | boxes queried, total_ms |
Errors
{ "error": { "code", "message" } }.
| HTTP | code | When |
|---|---|---|
| 400 | invalid_request | Not JSON, an unknown field, both or neither of gpx/geometry, a kind not listed, within_m out of range |
| 400 | invalid_gpx, invalid_coordinates | As for route analysis |
| 405 | method_not_allowed | Any method but POST (and OPTIONS) |
| 413 | body_too_large, too_many_points | Over 1 MB, or over 5,000 points |
| 422 | too_long, no_line | Over 300 km, or no line of two points |
| 422 | budget_exhausted | The job's 25 s budget ran out |
| 503 | places_unavailable | The places index did not answer; retry |
Versioning
Additive fields may appear in route-places/1. A change of meaning is route-places/2.