This document provides detailed information about all available endpoints in the Kyoto City Bus API.
All URLs referenced in the documentation have the following base:
http://localhost:8000
The public transit data used by this API is provided by the Public Transportation Open Data Center (ODPT) under the Public Transportation Open Data Basic License.
If you publish an application using this API, you are required to notify your end users of the following. Use the GET /kcb_api/info endpoint to fetch the notice text programmatically and display it in your app (e.g., in a help or disclaimer screen).
- The public transit data used in this application is provided by the Public Transportation Open Data Center.
- The data is based on information provided by the transit operator but is not guaranteed to be accurate or complete.
- Please do not contact the transit operator directly regarding the content displayed in this application.
All endpoints (except Health Check and Data Notice) require an API Key.
Include it in the request header X-API-Key.
X-API-Key: your_api_key_hereCheck operational status of the server.
- URL:
/kcb_api/health - Method:
GET - Auth: Not Required
{
"status": "healthy",
"timestamp": "2026-01-11T12:00:00"
}Returns data source information and the required user notice. Use this to display the notice to end users in your application.
- URL:
/kcb_api/info - Method:
GET - Auth: Not Required
Note for app developers: Display the
noticearray as-is to your end users. Thecontactfield contains the API owner's address — replace it with your own contact address in your app's disclaimer screen to satisfy the ODPT license requirement.
{
"data_source": "公共交通オープンデータセンター",
"data_source_url": "https://www.odpt.org/",
"operator": "京都市交通局",
"notice": [
"本アプリケーション等が利用する公共交通データは、公共交通オープンデータセンターにおいて提供されるものです。",
"公共交通事業者により提供されたデータを元にしていますが、必ずしも正確・完全なものとは限りません。",
"本アプリケーションの表示内容について、公共交通事業者への直接の問合せは行わないでください。"
],
"contact": "kmchan@kmchan.jp"
}Search for bus stops by name (partial match).
- URL:
/kcb_api/stops/search - Method:
GET - Auth: Required
| Name | Type | Required | Description |
|---|---|---|---|
q |
string | Yes | Search query (e.g., "京都") |
limit |
integer | No | Max results (1-50, default: 10) |
{
"success": true,
"query": "京都",
"count": 1,
"stops": [
{
"stop_name": "京都駅前",
"stop_ids": ["061211", "061212"]
}
]
}Find stops within a specified radius of GPS coordinates.
- URL:
/kcb_api/stops/nearby - Method:
GET - Auth: Required
| Name | Type | Required | Description |
|---|---|---|---|
lat |
float | Yes | Latitude (-90 to 90) |
lon |
float | Yes | Longitude (-180 to 180) |
radius |
integer | No | Radius in meters (max 5000, default: 500) |
limit |
integer | No | Max results (default: 20) |
{
"success": true,
"query": { "lat": 35.0, "lon": 135.7, "radius": 500, "limit": 20 },
"count": 2,
"stops": [
{
"stop_id": "012345",
"stop_ids": ["012345", "012346", "012347"],
"stop_name": "京都駅八条口",
"stop_desc": "Northbound",
"stop_lat": 35.001,
"stop_lon": 135.701,
"distance_meters": 150.5
}
]
}Fields:
stop_id: Representative stop ID (nearest platform)stop_ids: All stop IDs with the same stop name (all platforms)distance_meters: Distance to the nearest platform
Find direct bus routes between two stops.
- URL:
/kcb_api/search - Method:
POST - Auth: Required
{
"from_stop": "京都駅前",
"to_stop": "金閣寺道",
"current_time": "09:00",
"day_type": "weekday",
"date": "2026-01-12",
"limit": 3
}Parameters:
day_type:weekday,saturday, orsunday. Ignored ifdateis provided.date: (Optional) Search date inYYYY-MM-DDformat. When provided, holidays and special schedules are considered. Takes priority overday_type.
{
"success": true,
"count": 1,
"routes": [
{
"route_name": "205",
"trip_id": "205_weekday_123",
"headsign": "金閣寺道 / 北大路バスターミナル",
"departure_time": "09:05:00",
"departure_stop_desc": "B3",
"arrival_time": "09:45:00",
"arrival_stop_desc": "Main",
"travel_time_minutes": 40,
"stops_count": 12,
"fare": 230,
"service_id": "weekday_01"
}
]
}New Fields:
stops_count: Number of stops from departure to arrival (including both).fare: Bus fare in Japanese Yen (JPY). Returnsnullif fare information is unavailable.
Find routes with one transfer when no direct route is available.
- URL:
/kcb_api/search/transfer - Method:
POST - Auth: Required
{
"from_stop": "京都駅前",
"to_stop": "銀閣寺道",
"current_time": "09:00",
"day_type": "weekday",
"date": "2026-01-22",
"min_transfer_time": 5,
"limit": 3
}Parameters:
from_stop: Departure stop name (required)to_stop: Arrival stop name (required)current_time: Departure time in HH:MM format (optional, defaults to current time)day_type:weekday,saturday, orsunday(ignored ifdateis provided)date: Search date inYYYY-MM-DDformat (optional, considers holidays)min_transfer_time: Minimum transfer time in minutes (default: 5, max: 30)limit: Maximum results (default: 5, max: 10)
{
"success": true,
"query": { ... },
"count": 1,
"routes": [
{
"type": "transfer",
"total_time_minutes": 41,
"legs": [
{
"route_name": "市バス7",
"route_id": "00700",
"trip_id": "00700_01001_1298",
"headsign": "",
"departure_stop": "京都駅前",
"departure_stop_id": "061212",
"departure_stop_desc": "京都駅前(A2)",
"departure_time": "09:30:00",
"arrival_stop": "河原町丸太町",
"arrival_stop_id": "005400",
"arrival_stop_desc": "河原町丸太町(C)",
"arrival_time": "09:51:00"
},
{
"route_name": "市バス204",
"route_id": "20400",
"trip_id": "20400_01001_4556",
"headsign": "",
"departure_stop": "河原町丸太町",
"departure_stop_id": "005100",
"departure_stop_desc": "河原町丸太町(D)",
"departure_time": "09:56:00",
"arrival_stop": "銀閣寺道",
"arrival_stop_id": "103400",
"arrival_stop_desc": "銀閣寺道(B)",
"arrival_time": "10:11:00"
}
],
"transfer_info": {
"stop_name": "河原町丸太町",
"from_platform": "河原町丸太町(C)",
"to_platform": "河原町丸太町(D)",
"wait_minutes": 5
}
}
]
}Get the schedule for a specific stop.
- URL:
/kcb_api/timetable/{stop_id} - Method:
GET - Auth: Required
| Name | Type | Required | Description |
|---|---|---|---|
route |
string | No | Filter by route name |
day_type |
string | No | weekday (default), saturday, sunday |
{
"success": true,
"stop_id": "061211",
"stop_name": "京都駅前",
"count": 50,
"timetable": [
{
"departure_time": "09:00:00",
"route_name": "205",
"route_id": "00205",
"headsign": "金閣寺道",
"trip_id": "TRIP_123",
"service_id": "weekday_01"
}
]
}Estimate the current location of a specific bus trip based on the timetable.
- URL:
/kcb_api/trip/{trip_id}/location - Method:
GET - Auth: Required
| Name | Type | Required | Description |
|---|---|---|---|
time |
string | No | Reference time (HH:MM or HH:MM:SS). Default: current server time. |
departure_stop_id |
string | No | Your boarding stop ID. If provided, returns the previous 3 stops before boarding. |
{
"success": true,
"trip_id": "TRIP_123",
"query_time": "09:20:00",
"status": "between_stops",
"message": "河原町五条を出発 → 四条河原町に向かっています",
"from_stop": {
"stop_id": "STOP_A",
"stop_name": "河原町五条",
"time": "09:18:00"
},
"to_stop": {
"stop_id": "STOP_B",
"stop_name": "四条河原町",
"time": "09:22:00"
},
"estimated_arrival_minutes": 2,
"previous_stops": [
{
"stop_id": "STOP_X",
"stop_name": "祇園",
"time": "09:10:00"
},
{
"stop_id": "STOP_Y",
"stop_name": "清水道",
"time": "09:13:00"
},
{
"stop_id": "STOP_Z",
"stop_name": "東山三条",
"time": "09:16:00"
}
],
"boarding_stop": {
"stop_id": "STOP_BOARD",
"stop_name": "四条大宮",
"time": "09:25:00"
}
}New Fields (when departure_stop_id is provided):
previous_stops: List of up to 3 stops before your boarding stop (in order).boarding_stop: Your boarding stop information.
Status Values:
not_started: Bus has not left the first stop.between_stops: Bus is in transit.arrived: Bus has reached the final destination.
Error Responses:
-
400 Bad Request - Invalid time format:
{ "detail": "time must be in HH:MM or HH:MM:SS format (e.g., '9:30' or '09:30:00')" } -
400 Bad Request - Hour out of range:
{ "detail": "hour must be between 0 and 30 for GTFS compatibility" }
Here are complete examples using the requests library.
Define keys and base URL.
import requests
import json
from datetime import datetime
BASE_URL = "http://localhost:8000"
API_KEY = "your_actual_api_key_here" # Match .env
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}
def print_resp(resp):
print(json.dumps(resp.json(), indent=2, ensure_ascii=False))Find stop ID by name.
# Search for stops containing "Kyoto"
params = {"q": "京都", "limit": 5}
response = requests.get(f"{BASE_URL}/kcb_api/stops/search", headers=headers, params=params)
if response.ok:
print("Found stops:")
print_resp(response)Find stops near Kyoto Station (34.9858° N, 135.7588° E).
params = {
"lat": 34.9858,
"lon": 135.7588,
"radius": 300, # 300 meters
"limit": 5
}
response = requests.get(f"{BASE_URL}/kcb_api/stops/nearby", headers=headers, params=params)
print_resp(response)Search for a route and look up the timetable for one of the results.
# 1. Search for route
payload = {
"from_stop": "京都駅前",
"to_stop": "四条河原町",
"current_time": "10:00",
"day_type": "weekday"
}
resp = requests.post(f"{BASE_URL}/kcb_api/search", headers=headers, json=payload)
data = resp.json()
if data.get("count", 0) > 0:
top_route = data["routes"][0]
print(f"Top Route: {top_route['route_name']} (Trip ID: {top_route['trip_id']})")
# 2. Get Timetable for the departure stop of this route
stop_id = top_route["departure_stop_id"]
route_name = top_route["route_name"]
timetable_url = f"{BASE_URL}/kcb_api/timetable/{stop_id}"
params = {"route": route_name, "day_type": "weekday"}
ts_resp = requests.get(timetable_url, headers=headers, params=params)
print("\nTimetable for this route:")
print_resp(ts_resp)
else:
print("No route found.")Using the trip ID from the search result, check where the bus is.
trip_id = "target_trip_id_here" # Get this from search results
# Check location at 10:15
params = {"time": "10:15"}
loc_resp = requests.get(f"{BASE_URL}/kcb_api/trip/{trip_id}/location", headers=headers, params=params)
print("\nBus Location Status:")
print_resp(loc_resp)