Skip to content

Getting started

Create an API key in the dashboard and call the API. A secret key (rr_sk_…) goes in the Authorization header, on servers only:

Terminal window
curl -H "Authorization: Bearer $RAIL_API_KEY" https://api.routing.gleisklar.de/v1/dataset
{ "version": "20261104-0200", "built_at": "2026-11-04T02:41:07Z", "stale": false,
"format": …, "nodes": …, "edges": …, "segments": … }

(Illustrative values.) Every response names the data version that answered it in the X-Data-Version header. Errors are problem details; the API overview has the rules every endpoint shares, and the OpenAPI document is served at GET /v1/openapi.json.

Routes are POST /v1/route. Places are stations by code (DS100 AK, RINF UOPID DE000AK or UIC 8000199), coordinates or OpenStreetMap nodes; find a station’s code by name with GET /v1/places?q=.

Terminal window
curl -H "Authorization: Bearer $RAIL_API_KEY" -H "Content-Type: application/json" \
https://api.routing.gleisklar.de/v1/route -d '{
"from": { "station": "AK" },
"to": { "station": "AL" },
"vehicle": { "electrification": "any" }
}'
{
"status": "ok",
"stops": [
{ "name": "Kiel Hauptbahnhof", "kind": "station", "ds100": "AK", "lon": 10.1319, "lat": 54.3146,
"snapped": { "lon": 10.13201, "lat": 54.31455, "distance_m": 8.1 } },
{ "name": "Lübeck Hauptbahnhof", "kind": "station", "ds100": "AL", "lon": 10.6699, "lat": 53.8676, … }
],
"vehicle": { "gauge_mm": 1435, "train_type": "passenger", … },
"routes": [
{ "distance_km": 80.3, "duration_min": 58.6, "reversals": 0,
"legs": [{ "from": 0, "to": 1, "distance_km": 80.3, "duration_min": 58.6, "reversals": 0 }] }
],
"warnings": []
}

(Shortened, illustrative values.) Geometry, the infrastructure along the route, a running time estimate, borders and infrastructure managers and track access charges come with include, e.g. "include": ["geometry", "sections", "estimate"].

Terminal window
npm install @quebi/rail-api
import { createClient } from "@quebi/rail-api";
const api = createClient({ apiKey: process.env.RAIL_API_KEY });
const { results } = await api.places({ q: "Kiel Hbf" });
const answer = await api.route({
from: { station: "AK" },
to: { station: "AL" },
vehicle: { electrification: "any" },
});

Errors are thrown as RailApiError (with the problem’s status, type, title, detail and errors), or one of its subclasses such as NotFoundError or RateLimitError (with retryAfter).

For maps, railStyle() from @quebi/rail-api/maplibre builds a MapLibre style with the railway tiles, the key handling and the required “© OpenStreetMap contributors” attribution. Use a publishable key (rr_pk_…) in the browser.

railStyle("speed", { key: "rr_pk_…", basemap: "light" }) adds our own basemap under the tracks (land, water, roads and place labels, served by the API with its fonts and icons; flavours light, dark, white, grayscale, black). Without basemap the tracks are drawn on a plain background.