Your first request
Three steps take you from a stop name to the vehicles coming to it. Nothing to install for curl; JavaScript needs Node.js 18 or newer, Python needs nothing beyond the standard library.
0. Get a key#
After your application is approved, create a key in the developer cabinet. It is shown once. Keep it on your server, for example in an environment variable:
export IBUS_API_KEY='ibk_live_k_…'Every example below sends it in the Authorization header. Never put it in a URL, a web page or an app package.
1. Find the stop#
Search by name in Hebrew, English or Arabic, or by the code written on the stop sign.
curl -H "Authorization: Bearer $IBUS_API_KEY" "https://api.ibusisrael.online/api/transport/stops/search?q=Azrieli&limit=3&lang=en"const base = "https://api.ibusisrael.online/api/transport";
const res = await fetch(`${base}/stops/search?q=Azrieli&limit=3&lang=en`, { headers: { Authorization: `Bearer ${process.env.IBUS_API_KEY}` } });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
console.log(await res.json());import json, os, urllib.request
url = "https://api.ibusisrael.online/api/transport/stops/search?q=Azrieli&limit=3&lang=en"
req = urllib.request.Request(url, headers={"Authorization": "Bearer " + os.environ["IBUS_API_KEY"]})
with urllib.request.urlopen(req, timeout=15) as r:
print(json.load(r))[
{"stop_code": "34219", "stop_name": "Azrieli Mall", "stop_lat": 31.899117, "stop_lon": 35.007414},
{"stop_code": "21472", "stop_name": "Azrieli Mall/Menahem Begin Road", "stop_lat": 32.074584, "stop_lon": 34.790607}
]stop_code is the public code. Several stops can share a name: check the position or ask by code.
2. Ask for the arrivals#
curl -H "Authorization: Bearer $IBUS_API_KEY" "https://api.ibusisrael.online/api/transport/v2/stop/21472/arrivals?limit=5&lang=en"const base = "https://api.ibusisrael.online/api/transport";
const res = await fetch(`${base}/v2/stop/21472/arrivals?limit=5&lang=en`, { headers: { Authorization: `Bearer ${process.env.IBUS_API_KEY}` } });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
for (const a of data.arrivals) {
const when = a.freshness.state === "live" ? `${a.expected_in_min} min` : a.freshness.state;
console.log(a.route_short_name, a.dest_names?.en ?? a.destination_name, when);
}import json, os, urllib.request
url = "https://api.ibusisrael.online/api/transport/v2/stop/21472/arrivals?limit=5&lang=en"
req = urllib.request.Request(url, headers={"Authorization": "Bearer " + os.environ["IBUS_API_KEY"]})
with urllib.request.urlopen(req, timeout=15) as r:
data = json.load(r)
for a in data["arrivals"]:
state = a["freshness"]["state"]
when = f'{a["expected_in_min"]} min' if state == "live" else state
print(a["route_short_name"], a.get("dest_names", {}).get("en"), when)3. Read the freshness of each row#
freshness.state | Show it as |
|---|---|
live | A realtime prediction: expected_in_min, expected_arrival_utc. |
scheduled_confirmed | A timetable time: freshness.scheduled_arrival_utc. The vehicle's own report is old, the timetable confirms the trip. |
stale_observation | Last seen age_sec seconds ago; not a live prediction. When eta_hidden is true, do not show a time at all. |
unknown_age | The source gave no usable time; do not present it as live. |
The envelope's source_state tells whether the source answered: ok, no_data (it answered with nothing) or unavailable.
Keys are for servers. A web page or a mobile app calls your own server, and your server calls iBus with the key; cross-origin browser requests are allowed only for the iBus app.
Next#
- Data and time: service dates, times after midnight, identifiers.
- Limits and errors: what to do with
429and5xx. - API reference: every operation with examples.