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

Places along a route (curl)
# 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}'

Sends a real request, with your key or the keyless allowance.

Request body

FieldTypeDescription
gpxstringOne line as GPX (several parts allowed; distances skip the gaps). Or geometry, not both. Limits: 5,000 points, 300 km, 1 MB.
geometryobjectA GeoJSON LineString or MultiLineString, [lon, lat].
kindsarrayDefault all.
within_mnumberHow far from the line a place may lie.

Response

FieldTypeDescription
schemastring: route-places/1
engineobject
settingsobject
settings_defaultedarray
inputobject
sourceobject
placesarray
countsobject
waterobject or nullWhen 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).
unknownsarray
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=summer or a spring tagged intermittent=yes says 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 }
FieldDefault
gpx or geometryone of themAs for route analysis: 5,000 points, 300 km, 1 MB; several parts are allowed, and distances skip the gaps between them
kindsallAny 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_m100How far from the line a place may lie, 10 to 1,000 m
callerOptional label

Response

FieldMeaning
schemaroute-places/1
settings, settings_defaultedkinds and within_m as used
inputformat, parts, points, length_m (gaps excluded), gaps_m
sourcename, 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_idsOne 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
countsPlaces per asked category
waterWhen 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
timingboxes queried, total_ms

Errors

{ "error": { "code", "message" } }.

HTTPcodeWhen
400invalid_requestNot JSON, an unknown field, both or neither of gpx/geometry, a kind not listed, within_m out of range
400invalid_gpx, invalid_coordinatesAs for route analysis
405method_not_allowedAny method but POST (and OPTIONS)
413body_too_large, too_many_pointsOver 1 MB, or over 5,000 points
422too_long, no_lineOver 300 km, or no line of two points
422budget_exhaustedThe job's 25 s budget ran out
503places_unavailableThe places index did not answer; retry

Versioning

Additive fields may appear in route-places/1. A change of meaning is route-places/2.