Routes across borders
Track access charges are billed per infrastructure manager (IM), and a cross-border train has to
handle every electrification and train protection system on its way (for an estimate of the
charges per IM, see track access charges). POST /v1/route lists
them for each route in travel order, with km along the route, when you ask for them with
include:
include | Fields of each route | What |
|---|---|---|
countries | countries | {country, from_km, to_km, distance_km, source}: stretches by country (ISO 3166-1 alpha-2) |
border_crossings | {from_country, to_country, km, lat, lon, name?, source} | |
infrastructure_managers | infrastructure_managers | {im, im_code?, source, from_km, to_km, distance_km}: stretches by IM |
distance_by_im | {im, im_code?, distance_km, share}: km per IM, longest first; the shares sum to 1 | |
changes | changes | {km, kind, from, to, lat, lon}, kind electrification or train_protection |
curl -H "Authorization: Bearer $RAIL_API_KEY" -H "Content-Type: application/json" \ https://api.routing.gleisklar.de/v1/route -d '{ "from": { "station": "RF" }, "to": { "station": "8500010" }, "profile": "freight-electric-multisystem", "include": ["countries", "infrastructure_managers", "changes"] }'Freiburg (Breisgau) Hbf by its DS100 code, Basel SBB by its UIC code (find codes by name with
GET /v1/places?q=). Each route then carries, besides distance_km, duration_min, reversals
and legs:
"border_crossings": [{ "from_country": "DE", "to_country": "CH", "km": 62.4, "lat": 47.5638, "lon": 7.6359, "name": "Basel Bad Bf CH/BW", "source": "rinf" }],"distance_by_im": [{ "im": "DB InfraGO", "im_code": "0080", "distance_km": 62.4, "share": 0.93 }, { "im": "SBB Infrastruktur", "im_code": "0085", "distance_km": 4.7, "share": 0.07 }],"changes": [{ "km": 62.4, "kind": "train_protection", "from": "PZB", "to": "Integra-Signum", "lat": 47.5638, "lon": 7.6359 }](Illustrative values.) With the SDK:
const { routes: [trip] } = await api.route({ from: { station: "RF" }, to: { station: "8500010" }, include: ["countries", "infrastructure_managers", "changes"],});for (const b of trip.border_crossings ?? []) console.log(`${b.from_country} → ${b.to_country} at km ${b.km} (${b.source})`);for (const m of trip.distance_by_im ?? []) console.log(`${m.im}: ${m.distance_km} km`);for (const c of trip.changes ?? []) console.log(`km ${c.km} ${c.kind}: ${c.from} → ${c.to}`);Where the values come from
Section titled “Where the values come from”Each piece of track gets a value; the response groups equal values into stretches.
- Country: the country of the track’s RINF section of line (the member state that reports it to
ERA). Track without RINF data: the country of the IM its OpenStreetMap
operatortag names (DB InfraGO AG,ÖBB-Infrastruktur AG,SBB…), else the country of the nearest station whose code says (RINF UOPID prefix or UIC country digits, within 30 km).sourcesays which ofrinf,osmorstationsdecided most of the stretch. - Infrastructure manager: the organisation code RINF gives for the section (
0080DB InfraGO,0081ÖBB-Infrastruktur,0085SBB,0084ProRail …, named from a table of each RINF country’s main IM; others appear asIM 3023), else the OSMoperatortag (the known IM it means, or the operator as tagged). - Electrification system: RINF energy supply (
AC 15kV-16.7Hz), else OSMvoltageandfrequency, written as15 kV 16.7 Hz,25 kV 50 Hz,3 kV DC, ornonefor track without electrification. Electrified track of unknown voltage or frequency counts as unknown. - Train protection: RINF legacy systems and ETCS level, plus OSM
railway:pzb/lzb/etcs, sorted and joined:PZB,LZB+PZB,ETCS+PZB,Integra-Signum;nonewhere RINF reports none. - Border crossing: where the country changes. It is placed at an OSM
railway=bordernode on the route within 3 km of the change (sourceosm, named after the node), else where the RINF sections of the two countries meet (rinf, named after the operational point they share), else between the two stretches (estimate).
Short and unknown stretches
Section titled “Short and unknown stretches”Stretches under 200 m (a switch, a crossover, one oddly tagged way) are ignored. Unknown stretches
under 1 km are bridged: merged when both sides agree, else split halfway. Longer unknown stretches
are reported as unknown (a country, an IM, or the from/to of a change), not attributed to a
neighbour: a 3 km stretch without an IM shows up as unknown in distance_by_im.
Accuracy
Section titled “Accuracy”- With RINF on both sides, countries, IMs and borders are accurate to the OpenStreetMap way the section was matched to (typically a few hundred metres).
- RINF reports border stations by the IM that runs them: Basel Bad Bf, on Swiss soil, is in the German
data up to the operational point
Basel Bad Bf CH/BW. The route’scountriesfollow RINF there, which is what matters for track access. - Track that RINF doesn’t cover (sidings, unmatched ways, countries whose RINF can’t be placed yet,
e.g. Switzerland) relies on the OSM
operatortag, then on the nearest station: such a border can be off by up to half the distance between the last stations on either side (estimate), unless OSM maps arailway=bordernode there.