Skip to content

Live sources ​

Everything live in Kav comes from one place, the live source:

  • vehicles on the map
  • stop boards
  • the planner's live updates
  • the recorded passings the predictor learns from

By default that's the Israeli Ministry of Transport's real-time service, with your own key. Any other source works too, as long as it answers the same questions the same way: SIRI StopMonitoring (CEN/TS 15531, the European standard the ministry also speaks), in JSON, version 2.8. Point Kav's server at it with:

LIVE_URL=http://my-source:8100/siri

A key is optional. When MOT_KEY is set, it's sent as Key= on every question.

The two questions ​

Kav's server asks your source exactly two things, as GET requests with these query parameters:

QuestionQueryWhen
All active tripsMonitoringRef=AllActiveTripsFilter&StopVisitDetailLevel=normalEvery 15 seconds while phones are looking, every 30 otherwise
Arrivals at stopsMonitoringRef=<code>,<code>,…&StopVisitDetailLevel=normal&PreviewInterval=PT90MWhen a stop board opens, at most once every 15 seconds per stop

The answer to both is the same shape:

json
{"Siri": {"ServiceDelivery": {
  "ResponseTimestamp": "2026-11-07T09:00:05+02:00",
  "StopMonitoringDelivery": [{"MonitoredStopVisit": [ <visit>, … ]}]
}}}

A visit ​

json
{"RecordedAtTime": "2026-11-07T09:00:01+02:00",
 "MonitoringRef": "21345",
 "MonitoredVehicleJourney": {
   "LineRef": "10966",
   "PublishedLineName": "8",
   "OriginAimedDepartureTime": "2026-11-07T08:40:00+02:00",
   "VehicleRef": "7712345",
   "FramedVehicleJourneyRef": {"DataFrameRef": "2026-11-07", "DatedVehicleJourneyRef": "30027349"},
   "VehicleLocation": {"Latitude": "32.0754", "Longitude": "34.7749"},
   "Bearing": "90", "Velocity": "23",
   "MonitoredCall": {"StopPointRef": "21345", "Order": "12",
                     "AimedArrivalTime": "2026-11-07T09:04:00+02:00", "ExpectedArrivalTime": "2026-11-07T09:05:30+02:00",
                     "ArrivalPlatformName": "2"}}}
FieldNeededWhat Kav uses it for
LineRefyesThe route's id in the timetable (GTFS route_id). A number (see Ids below)
OriginAimedDepartureTimeyesWhen the trip left its first stop: with LineRef, which trip this is
RecordedAtTimeyesWhen the vehicle reported. A position more than about 2 minutes old isn't shown as live
VehicleReffor the mapWhich vehicle it is, so it glides from report to report instead of jumping
VehicleLocationfor the mapWhere it is. Without it, the trip still shows on boards, just not on the map
MonitoredCall.StopPointRef, MonitoringRefyesThe stop: the one the vehicle is at or just passed (all trips), or the one asked about (arrivals). The stop's code (GTFS stop_code)
MonitoredCall.Orderfor historyThe stop's place on the trip, for the recorded passings
MonitoredCall.ExpectedArrivalTimefor boardsWhen it's expected at the stop (AimedArrivalTime, the timetable's, as a fallback)
PublishedLineNamefor boardsThe line's number as riders know it
FramedVehicleJourneyReffor the plannerThe trip's own id and service day, for the planner's live updates
Bearing, VelocityoptionalWhich way it faces (degrees), its speed (km/h)
ArrivalPlatformName / DeparturePlatformNameoptionalA train's platform

Times are ISO 8601 with their UTC offset. Anything outside the area in BOUNDS (south,west,north,east) is ignored. It's Israel by default, and a server can narrow it to one city.

Ids ​

Kav is for Israel: route ids (LineRef) and stop codes are the Ministry of Transport's own, as in its timetable, and they are numbers. A live source has to name trips and stops by those same ids.

Ready-made sources ​

  • The ministry (MOT_URL, MOT_KEY): the default.
  • GTFS-Realtime, the other open live format: server/examples/gtfsrt_siri.py converts a feed's vehicle positions and trip updates into these answers. It needs the ministry's ids, so it suits a feed built on the ministry's timetable.
  • A recording: server/examples/live_replay.py serves a recorded answer with its times moved to now, for trying it with no key at all, or as a starting point for your own source.

Kav ships adapters only for open, permitted sources. Whatever you connect to your own server is up to you, and on you.

Saving a recording ​

A recording for live_replay.py is one answer to the all-active-trips question. With a ministry key of your own, on the machine the ministry approved it for, ask it as Kav's server does:

sh
curl -s --cacert server/selfhost/mot-ca.crt \
  "https://moran.mot.gov.il/Channels/HTTPChannel/SmQuery/2.8/json?Key=$MOT_KEY&MonitoringRef=AllActiveTripsFilter&StopVisitDetailLevel=normal" \
  > recorded.json

mot-ca.crt is the certificate chain the ministry's server needs, as live.py uses it. Any other source's answer to the same question works too.

Checking yours ​

sh
python3 server/conformance.py live http://my-source:8100/siri

It asks both questions and lists exactly what's missing or wrong. If your source breaks later, Kav's server keeps the last snapshot for a while, then shows nothing live. The app says so, and nothing else breaks.