Conventions

What is the same across every call: where to send it, how to authenticate, which way round coordinates go, the units, and what an error looks like.

Hosts

  • https://api.trailsplits.com: everything except weather: maps and tiles, terrain, routing, route analysis, round trips, route weather, search, trails, outdoor places, static maps, map matching and snow.
  • https://trailsplits.com/api/weather/forecast: weather forecasts.

Both answer cross-origin requests from browsers (CORS). Everything runs in one region (Helsinki, Finland).

Keys and limits

  • No key: 500 credits a day per address, 5 requests per second. Good for trying things and for small demos.
  • With a key (free, from the API console): send Authorization: Bearer <key>. Calls count against your project's monthly credits and burst rate; usage per operation is in the console and at GET /v1/usage.
  • Heavy requests (round trips, route analysis, route weather) also have a limit on how many run at once: 1 without a key or on Free, then 2, 4 and 8 on larger plans. Over it: 429 concurrency_limit, Retry-After: 2.
  • Area lookups (/pois/v1/bbox, /trails/v1/bbox) have a daily ceiling per project: three times the plan's daily average credits (3,000 on Free), then 429 bbox_daily_ceiling until the next UTC day.
  • Browser keys (ts_pub_…) work only from the web origins you list in the console, at 2 requests a second per visitor; elsewhere 403 origin_not_allowed.
  • Secret keys (ts_live_…) are for servers: don't put one in an app or a web page. A web page uses a browser key or the keyless allowance.
  • Map tiles, styles and the manifest need no key and are not counted. What each call costs: plans and limits.

Coordinates

WGS84 degrees. The newer /v1 calls and all JSON results use [lon, lat], as GeoJSON does. Query strings that predate them use lat,lon. Per call:

WhereOrderExample
Route analysis, round trips, route weather (bodies)[lon, lat] (GeoJSON)"start": [7.7491, 46.0207]
Search and reverse resultscenter: [lon, lat]"center": [7.6586, 45.9764]
Elevation sample (query)points=lat,lon|lat,lonpoints=46.5369,12.1352|46.536,12.133
Weather (query)p=lat,lon[,elevation];…p=46.0207,7.7491,1608
Snow along a route (query)points=lat,lon|…points=46.0207,7.7491|46,7.7
Reverse search (query)lat=…&lon=…lat=46.0207&lon=7.7491
Outdoor places (query and records)min_lat, min_lon, max_lat, max_lon; records have lat, lonmin_lat=46&min_lon=7.7&max_lat=46.05&max_lon=7.8
Trail bbox (query)min_lat, min_lng, max_lat, max_lng (lng, not lon)min_lat=46&min_lng=7.7&…
Legacy route and trace attributes (bodies){"lat": …, "lon": …} objects{"lat": 46.5369, "lon": 12.1352}
bbox and bias_bbox (search, static map)minLon,minLat,maxLon,maxLatbias_bbox=7.5,45.9,7.9,46.1

Lines in answers (shape, geometry of routes) are polyline6: the encoded string holds lat,lon pairs at 1e-6 precision; decode to [lon, lat] for GeoJSON. The input line you send is never rewritten.

Units and time

  • Distances and heights in metres, durations in seconds or named minutes (minutes). One exception: trace attribute edge length is in kilometres, as in Valhalla.
  • Temperature °C, precipitation mm, wind km/h, probabilities %.
  • Times are ISO 8601. Inputs need an offset (2026-10-03T08:00:00+02:00 or …Z). Weather dates are local to each point; usage periods are UTC months.
  • A value that is not known is null, never 0. Unknowns are listed rather than guessed (for example unknowns[] in route analysis).

Errors

Every error is JSON with a stable code and a message you can show. There are three shapes, by family:

Error shapes
// The gateway (keys, limits): every API-host call can answer this way
{ "error": "monthly_credits_exhausted", "status": 429, "message": "This project has used its 30,000 credits for October.", "limit": "monthly_credits", "retry_after": 1234567 }

// The /v1 operations (route analysis, round trips, route weather) and weather
{ "error": { "code": "too_long", "message": "a hike round trip may be at most 40 km here; ask for a shorter one" } }

// The legacy route call (Valhalla-style)
{ "error": "…", "status_code": 400, "trailsplits": { "code": "unsupported_costing", "message": "…" } }

StatusMeaningCredits
400The request is malformed or outside the documented options.none
401credential_invalid: unknown, revoked or rotated key.none
403origin_not_allowed: a browser key used from an origin not on its list; scope_denied: a key used where a signed-in account is needed.none
413Body or point count over the limit.none
422Understood but not answerable: no route, no loop, line too long, outside coverage.counted where work was done (for example "no route")
429rate_limit, concurrency_limit, bbox_daily_ceiling, keyless_daily_credits_exhausted or monthly_credits_exhausted; wait Retry-After seconds.none
502 / 503A data source or the service is briefly unavailable (forecast_unavailable, overloaded, accounting_unavailable); retry after Retry-After.none

Versions and changes

  • Answers name their schema (route-analysis/1, weather-forecast/1, …). New fields can appear at any time; ignore what you don't use.
  • A breaking change (removing a field or endpoint, or changing its meaning) gets a new schema version and is announced on the changelog, normally 30 days ahead, as the API terms say.
  • Data is refreshed weekly. The same request can give a better answer next week; answers carry the release they used (engine.tiles.release, artifact_version).

Caching

Follow each answer's Cache-Control. Versioned map assets are immutable; computed answers vary. You may keep computed answers for up to 30 days to serve your users (terms).

The legacy route call

POST /route/v1 takes a subset of the Valhalla request format (locations as {lat, lon}, costing pedestrian or bicycle) and answers in the OSRM shape (polyline6, metres, seconds), with TrailSplits provenance in trailsplits. It does not follow the /v1 house style; the route reference covers it in full.

Attribution

Show “© TrailSplits” and the credits that come with the data (OpenStreetMap contributors, and the source of terrain, imagery or weather) wherever you show it. See the attribution and ODbL guide.