Brief Description
GTFS Realtime (GTFS-RT) is an extension to GTFS Static and enriches the static transit information with real-time information. The GTFS Realtime data is coordinated with the GTFS Static data. The realtime feed includes all known changes in the Swiss public transport system in the entire preview window (three hours) for all transport companies providing real-time data.
Access to the API:
Note: A description of how to access the APIs can be found here: Howto: Accessing our APIs with API Keys.
Functional Description
GTFS-RT allows the enrichment of static transit information with three different types of additional information. These three enrichments are usually delivered individually via HTTP and are regularly updated, allowing developers to choose with which real-time data to enrich their applications.
The three types of supplementary information are:
- Trip updates (which are mainly described here)
- Service Alerts (GTFS-SA)
- Vehicle Positions (will not be published on the Open data platform mobility Switzerland)
The Swiss GTFS profile, which describes in detail the properties adopted from the standard or deviating from the standard, can be found here: https://www.oev-info.ch/datenmanagement/ski/standards-der-ski (the link takes you to the overview page because the document (General Transit Feed Specification (GTFS) PROFILES SWITZERLAND) is still frequently adapted at present).
Please note: No updates are made on public holidays (e.g. Easter Monday, Whit Monday, etc.).
Trip Updates
Example: ‘Bus 18 is currently delayed by 10 minutes.’
Delays, changed routes, replacement vehicles or cancellations for individual lines are published on an ongoing basis to enable passengers to plan as accurately as possible.
As long as a SJYID is not always sent via VDV454, the VDV454 FahrtBezeichner (journey identifier) is sent in GTFS-RT in original_trip_id in cases where no SJYID is available:
// Matches the original_trip_id in GTFS static.
optional string original_trip_id = 8;Service Alerts
Example: ‘Stop’ Bern, Weissenbühl is currently closed due to an accident.’
If the boarding area is moved or if there are unforeseen events in general that affect a stop, a route or the entire network, short messages can be published to keep passengers up to date and explain the reason for the change.
Data set GTFS-RT: Service Alerts
Cookbook: GTFS-RT: Service Alerts (incident information Switzerland)
Vehicle positions
Example: ‘This bus is at the bus stop at 18:23 Bern, station.‘
Information on the location of individual transit vehicles can be published here. In addition, the current occupancy rate of the vehicle, the vehicle type or similar information can also be provided.
The vehicle positions are not available on the platform.
Key concepts
- GTFS Static (also known as GTFS Schedule): Publication of static transit information in GTFS format.
- GTFS Realtime: Publication of real-time transit information as an enrichment of the static GTFS data, in the form of protocol buffers.
The individual elements are explained in detail on the above pages of the standard, so they are not all reproduced here.
Technical Description
Trip updates are provided via a GET request. They are cached for 30 seconds, meaning there is only new data twice per minute.
To optimise our caching, the API manager sends a redirect with a new link, so redirects must always be enabled when using this service. For many code libraries, this can be done with appropriate parameters such as ‘allow_redirects’.
Authorization and Open Services
An API key is required in order to access this API. It can be obtained via our API Manager, see the instructions in Howto: Accessing our APIs with API keys.
Maximum number of queries per minute
You can use your key to make a maximum of two queries per minute on the interface. This is a sliding window.
If a request is sent too quickly, the following message will return:
{
"error": "Rate limit exceeded"
}Related to GFTS Static
Each GTFS RT feed is based on a GTFS static. This is provided on Mondays and Thursdays (for service disruption, see next section). At 3pm each time, the GTFS RT feed is switched to the new GTFS Static. Since identifiers (‘service_id,’ ‘trip_id’) can change with any version of the GTFS Static, reference to the correct GTFS Static is key for a correct implementation of the interface.
| Publication GTFS-S | Activation GTFS-RT |
|---|---|
| Monday between 9am and 10am | Monday 3 p.m. |
| Thursday between 9 a.m. and 10 a.m. | Thursday 3 p.m. |
In the header, reference is made to the relevant GTFS static version in the feed_version element (notation in .json: FeedVersion). When viewed as JSON, the header could look like this (use JSON only for testing, see below):
"Header": {
"GtfsRealtimeVersion": "1.0",
"Incrementality": "FullDataset",
"Timestamp": 1727429583,
"FeedVersion": "20240926"
}In case of disruption
The GTFS Static Export is published as soon as possible, followed by GTFS Realtime approx. 5-6 hours later, but no later than 6pm of the same day. If this is not possible, the new data will be activated in GTFS Realtime the following day.
Example: The new GTFS static data could only be published in the afternoon. The activation of the GTFS real-time data follows at approx. 08:00 the next day
URL for the call
HTTP GET auf https://api.opentransportdata.swiss/la/gtfs-rt(Note: No end ‘/’)
Headers:
- Content type: ‘application/octet-stream’
- User-Agent must be set (any value)
- ‘Accept-Encoding: br, gzip, deflate’
- Redirections must be allowed.
Example in curl
curl -H "Authorization: Bearer eyJvcmciOiI2NDA2NTFhNTIyZmEwNTAwMDEyOWJiZTEiLCJpZCI6ImZjNzdjMzk2M2MwNjRjYzM4ZmNjOWZjYWQ4MjVlZWZkIiwiaCI6Im11cm11cjEyOCJ9" -L -H "User-Agent: testuser" https://api.opentransportdata.swiss/la/gtfs-rt --compressed --output gtfs_rt_as_proto_buf.pbStructure of the data (Protocol Buffer)
The GTFS Realtime data format is based on protocol buffers, which is a language and platform-neutral mechanism for putting data in a serial order. It is designed as a binary format, which makes it smaller, faster and simpler than XML. The data structure is in a so-called gtfs-realtime.proto-File defines which is used to generate source code to easily translate the structured data into different languages (Java, C++, Python, etc.).
Structure of data (JSON)
Alternatively, the platform also provides a JSON implementation.
The request is then made via the URL:
HTTP GET https://api.opentransportdata.swiss/la/gtfs-rt?format=JSONHowever, the JSON variant is not standardized.
Use of JSON for testing purposes only
JSON may only be used for testing purposes if, for example, a developer of a new app wants to see in readable form what data is contained in our GTFS RT.
Ultimately, the GTFS-RT interface should not be operated in readable JSON, but in binary (without ?FORMAT=JSON) for the following reasons:
- binary is much more powerful than JSON and much more data has to be transmitted and imported into JSON (a JSON report can be up to approx. 11MB in size),
- JSON is unspecified, but with binary GTFS RT, the GTFS client can rely on it to comply with the GTFS RT standard
Accuracy
Delays are accurate to one tenth of a minute (0.1 min = 6 s).
Interpretation of the data
For the exact interpretation of the data, the GTFS specification can be consulted directly.
The biggest special case are the platforms which are located on the GTFS Page are described.
Other important points
- GTFS-RT only returns new data if something has changed. Our system only observes the departure forecast. If the departure forecast remains and only the arrival forecast changes, no GTFS-RT message is generated for the relevant journey.
- If a journey runs on time, it is displayed with ‘Delay’ within StopTimeUpdate: 0.
- Example
{
"id": ".ojp-92-206.1.TA.50.j26|20260624",
"tripUpdate": {
"trip": {
"tripId": ".ojp-92-206.1.TA.50.j26",
"startTime": "12:41:00",
"startDate": "20260624",
"scheduleRelationship": "SCHEDULED",
"routeId": "92-206-j26-1",
"originalTripId": "85:876:6037_103"
},
"stopTimeUpdate": [
{
"stopSequence": 1,
"departure": {
"delay": 0
},
"stopId": "ch:1:sloid:93924:0:2",
"scheduleRelationship": "SCHEDULED"
},
{
"stopSequence": 8,
"arrival": {
"delay": 30
},
"departure": {
"delay": 30
},
"stopId": "ch:1:sloid:93932:0:1",
"scheduleRelationship": "SCHEDULED"
},
{
"stopSequence": 9,
"arrival": {
"delay": 0
},
"departure": {
"delay": 0
},
"stopId": "ch:1:sloid:93933:0:1",
"scheduleRelationship": "SCHEDULED"
}
]
}
},
Questions & answers
| What does a real-time message mean without ‘stop_time_updates’? | Real-time messages without ‘stop_time_updates’ are triggers without real-time. Changes have been made in this regard so that journeys without real-time are no longer transmitted. |
| Could it be that on lines with poor data quality a gtfsrt entity with delay=0 is always returned instead of no gtfsrt entity at all? | No, this is not the case. Either a journey has real time and all delays are also shown, or it does not have real time. Delay 0 stands for real time and on time. Either we did not receive a delay in VDV 454 AUS or we were unable to process the message with the forecast. |
