Use case · STIB-MIVB

STIB GTFS Realtime (GTFS-RT)

STIB-MIVB publishes no GTFS-RT feed. Its real-time API says where vehicles are, but not which vehicle or which trip. MobilityTwin.Brussels reconstructs both, every 20 seconds, and publishes them as standard GTFS-RT Vehicle positions and Trip updates, with the trip, route and stop ids of STIB's own GTFS.

The feeds

Base URL https://api.mobilitytwin.brussels. Every vehicle-trip snapshot is archived: add ?timestamp= (epoch or ISO) for a past moment, or /index to list a period's snapshots. The two GTFS-RT feeds are built from it on request; add ?end_timestamp= (epoch) for a feed as it stood at a past moment.

How it works

Every 20 seconds STIB reports each vehicle as a line, a destination, the last stop it passed and the metres since. Nothing else — no vehicle number, no trip. Four steps turn that into GTFS-RT.

  1. 1. Place

    Each position is put on its line as metres from the start, using the stop order of the day's GTFS.

  2. 2. Track

    Vehicles on a line do not overtake each other, so their order is the same from one poll to the next. Each poll is aligned with the previous one in that order, like a diff, which gives every vehicle an identity that lasts its whole run.

  3. 3. Read stop calls

    When the reported stop changes, the vehicle has just reached a new one; the moment is interpolated between the two polls around it.

  4. 4. Match trips

    The vehicles on the road are paired with the timetabled trips that could be running, choosing the pairing with the smallest total gap between observed and scheduled stop times. The gap at the last stop is the delay, carried to the stops ahead.

It is the live form of the method behind the daily STIB punctuality table, which does the same with a whole day in hand.

Quality, and what it cannot tell

91%

of vehicles that have left their first stop carry a trip.

93%

of those trips are the ones the daily reconstruction picks with a whole day of hindsight (88% at the morning peak).

~1 min

after leaving its first stop, a vehicle has its trip (two stop calls).

How to use it

Create a free account and a token on your account page. Send it as Authorization: Bearer <token>, or, for tools that only take a URL, as ?token=<token>.

Python

import requests
from google.transit import gtfs_realtime_pb2   # pip install gtfs-realtime-bindings

url = "https://api.mobilitytwin.brussels/stib/gtfs-rt-trip-update"
data = requests.get(url, headers={"Authorization": "Bearer <token>"}).content

feed = gtfs_realtime_pb2.FeedMessage.FromString(data)
for entity in feed.entity:
    update = entity.trip_update
    print(update.trip.trip_id, update.delay, "s late")

OpenTripPlanner 2 (router-config.json)

"updaters": [
  {
    "type": "stop-time-updater",
    "feedId": "stib",
    "frequency": "20s",
    "url": "https://api.mobilitytwin.brussels/stib/gtfs-rt-trip-update",
    "headers": { "Authorization": "Bearer <token>" }
  },
  {
    "type": "vehicle-positions",
    "feedId": "stib",
    "frequency": "20s",
    "url": "https://api.mobilitytwin.brussels/stib/gtfs-rt-vehicle-position",
    "headers": { "Authorization": "Bearer <token>" }
  }
]

Pair it with STIB's static GTFS of the same day, available as /stib/gtfs (zip) or /stib/gtfs-parquet. For bulk history, the Python client downloads a period's snapshots, resumably.