Quickstart
Three requests and a warning: check the server is up, ask a real question, then find out why the answer looks the way it does.
1. There is no key
The API takes no credential. No sign-up, no token, no header — just call it. That is why the Try it consoles on this site are real: with nothing to authenticate, a browser can reach the API directly. See Access, CORS and errors.
The only thing to set is where your API lives. Everything on this site uses
$API_BASE, so export it once:
export API_BASE=https://gtfs-realtime-api.broad-darkness-36e7.workers.dev 2. Check the server
/health is the cheapest way to tell “the server is down” from
“my query is wrong”.
curl "$API_BASE/health" {
"status": "ok",
"feed": {
"loadedAt": "2026-08-07T12:01:42.748Z",
"files": 3,
"entities": 2227
}
} entities is vehicles plus trip updates plus alerts. If it reads 0,
the data directory failed to load and every other endpoint will come back empty — check
/api/feed, which reports each file separately.
3. Ask something real
Buses on route 875, as GeoJSON, inside a box over central Stockholm — three filters that compose.
curl "$API_BASE/api/vehicles?routeId=9011001087500000&limit=5"
# the same vehicles as GeoJSON, boxed to central Stockholm
curl "$API_BASE/api/vehicles?bbox=17.9,59.30,18.15,59.36&format=geojson&limit=5"
# what is calling at Tyresö centrum, station id and all its platforms
curl "$API_BASE/api/stops/778/arrivals?limit=5"
Lists come back as { data: [...], meta: { count, total, limit, offset, feedTimestamp, loadedAt } }. total is the match count before paging, so compare it against
offset + count to know when you have them all. Single items come back as
{ data: {...} } with no meta.
4. Know what will surprise you
There is a third that is less obvious and more useful: a good number of the documented filters match nothing in this particular capture, because the SL feed simply never populates the fields they filter on. Occupancy, congestion, alert severity and trip-level delay are all absent from every entity. Each one is called out on its parameter row in the reference, and flagged in the console, so you never have to guess whether an empty result means “none matched” or “this filter cannot match”.