-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
Justintunsday edited this page Sep 14, 2026
·
2 revisions
- 基础地址(自部署时替换为你的域名):
https://ts-api.tundrey.com - 全部端点为
GET,返回 JSON(UTF-8) - 端点索引:
GET /或GET /v1 - 时间均为北京时间;距离单位米;时长单位秒
默认关闭。若部署时设置了 API_KEY 环境变量,所有 /v1/* 请求需携带以下任意一种凭证:
| 方式 | 示例 |
|---|---|
请求头 X-API-Key
|
curl -H "X-API-Key: <key>" ... |
| Bearer Token | curl -H "Authorization: Bearer <key>" ... |
| 查询参数 | curl "...?key=<key>" |
{
"error": {
"code": "invalid_params",
"message": "One or more request parameters are invalid.",
"details": [{ "param": "lat", "message": "must be a decimal number, e.g. '31.230416'" }]
}
}| HTTP | code | 说明 |
|---|---|---|
| 400 | invalid_params |
参数缺失、格式错误、越界 |
| 401 | unauthorized |
已启用 API Key 但未提供 / 不正确 |
| 403 | origin_not_allowed |
来源不在 CORS 白名单 |
| 404 | not_found |
路径不存在 |
| 405 | method_not_allowed |
使用了非 GET/HEAD/OPTIONS 方法 |
| 429 | rate_limited |
触发限流(响应带 Retry-After: 60) |
| 502 | upstream_error |
上游返回异常或响应无法解析 |
| 504 | upstream_timeout |
上游超时(默认 15s) |
- 默认
Access-Control-Allow-Origin: *,可直接在浏览器前端调用。 - 服务端可选按 IP 限流(部署时设置
RATE_LIMIT_PER_MINUTE)。
| 端点 | Cache-Control |
|---|---|
/v1/cities |
public, max-age=3600(live=true 时 no-store) |
/v1/cities/config |
public, max-age=600 |
/v1/reverse-geocode |
public, max-age=86400 |
/v1/lines/route |
public, max-age=86400 |
/v1/lines/timetable |
public, max-age=3600 |
| 实时类端点 | no-store |
坐标系(WGS-84 / GCJ-02)与字段含义见 Coordinates-and-Fields。
存活探针,无参数。
{
"status": "ok",
"name": "chelaile-api",
"version": "2.0.0",
"time": "2026-09-14T11:00:00.000Z",
"uptimeSeconds": 42
}支持的城市列表。默认读静态数据集(GitHub/jsDelivr 或本地文件),不占用上游配额。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
hot_only |
boolean | true |
只返回热门城市(12 个);false 返回全部 480 个 |
live |
boolean | false |
true 时忽略数据集直接回源上游 |
boolean 参数接受 true/false、1/0。
{
"origin": "github",
"updatedAt": "2026-09-14T08:54:05.173Z",
"hotOnly": true,
"count": 12,
"total": 480,
"cities": [
{ "cityId": "034", "cityName": "上海", "pinyin": "ShangHai", "supportSubway": true, "hot": true }
]
}origin 取值:github(CDN/仓库)、file(本地文件)、upstream(实时上游)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID,如 034
|
{
"maxInterval": 30,
"arrivingStationLimitSeconds": 180,
"busDisplayConfig": { "lineDetail": "time#order#distance", "other": "time#order" }
}WGS-84 经纬度 → 中文地址。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
lat |
number string | 是 | WGS-84 纬度 |
lng |
number string | 是 | WGS-84 经度 |
{
"formatted": "上海市黄浦区南京东路街道延安高架路凯迪拉克·上海音乐厅",
"province": "上海市",
"city": "上海市",
"district": "黄浦区",
"township": "南京东路街道",
"citycode": "021",
"adcode": "310101"
}按 IP 估算位置,精度城市级(约 10 km)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
ip |
string | 否 | 指定 IP;省略时使用服务器出口 IP,部署在大陆的服务器更准确 |
{
"lat": 31.2222, "lng": 121.4581, "gpsType": "wgs",
"city": "上海", "region": "上海市", "country": "中国",
"ip": "116.236.0.1", "isp": "China Telecom",
"precision": "city-level (~10 km); not suitable for stop-level queries",
"inChina": true
}境外 IP 会返回 inChina: false 并附带 warning。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
keyword |
string | 是 | 关键词,如 71、71路、地铁2号线、陆家嘴
|
{
"highlightKey": "71",
"lines": [
{
"name": "71", "lineNo": "r95817", "isSubway": false,
"directions": [
{ "direction": 0, "lineId": "21283603183", "startSn": "延安东路外滩", "endSn": "申昆路枢纽站" },
{ "direction": 1, "lineId": "21283603182", "startSn": "申昆路枢纽站", "endSn": "延安东路外滩" }
],
"lineId": "21283603183", "direction": 0, "startSn": "延安东路外滩", "endSn": "申昆路枢纽站"
}
],
"stations": [
{
"sId": "021-15232", "sn": "西藏中路",
"lat": 31.231006, "lng": 121.474316, "gpsType": "wgs",
"physicalStId": "2868ecd4156f42b4b4cd38bfbd5dcb00",
"namesakeStId": "c2bd23ef55aa0701976b156087099c9c",
"isSubway": false
}
],
"pois": [
{ "name": "71路", "address": "中山东一路", "tag": "公交线路", "district": "黄浦区", "lat": 31.233021, "lng": 121.49073, "gpsType": "gcj" }
]
}要点:
- 同线路上下行折叠进
directions[];顶层lineId/direction/startSn/endSn是 direction=0 的兼容字段。 -
stations[].lat/lng为 WGS-84;pois[].lat/lng为 GCJ-02。 -
isSubway: true的线路不支持/v1/lines/detail(返回empty: true),改用/v1/stops/detail或/v1/transit/plan。
与 /v1/search 同参,另加:
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
type |
"1" | "2" | "3" |
"1" |
1 更多线路、2 更多站点、3 更多 POI |
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
city_id |
string | 是 | 城市 ID | |
lat / lng
|
number string | 是 | WGS-84 坐标 | |
limit |
integer | 否 | 5 |
返回最近站点数,1–20 |
{
"stops": [
{
"sId": "021-15232", "sn": "西藏中路", "distance": 87, "isSubway": false,
"physicalStId": "2868ecd4156f42b4b4cd38bfbd5dcb00",
"namesakeStId": "c2bd23ef55aa0701976b156087099c9c",
"lines": [
{
"lineId": "21283603183", "name": "71", "direction": 0, "endSn": "申昆路枢纽站",
"status": "", "targetOrder": 2, "targetStationId": "021-15232",
"buses": [
{ "busId": "021-15232-1", "order": 2, "arrivalTime": 1779070466055, "travelTime": 90, "distanceToDest": 881, "capacity": 0 }
]
}
],
"subwayLines": []
}
]
}lines[].lineId + lines[].targetOrder + lines[].targetStationId 可直接用于 /v1/lines/realtime。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
physical_st_id |
string | 是 | 来自 /v1/stops/nearby 或 /v1/search
|
namesake_st_id |
string | 否 | 建议携带,来自同一来源 |
first_line_id |
string | 否 | 高亮某条线路 |
lat / lng
|
number string | 否 | 传入后返回 distance
|
{
"stations": [
{
"sId": "021-15232", "sn": "西藏中路", "lat": 31.231006, "lng": 121.474316,
"lines": [
{
"lineId": "21283603183", "name": "71", "direction": 0,
"startSn": "延安东路外滩", "endSn": "申昆路枢纽站",
"firstTime": "05:30", "lastTime": "23:30", "price": "2元",
"targetOrder": 2, "buses": []
}
],
"metros": [{ "name": "地铁2号线", "lineNo": "2号线", "color": "140,194,32" }]
}
]
}stations[] 多项表示该站名对应多个物理站台。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
line_id |
string | 是 | 线路 ID(来自 /v1/search) |
lat / lng
|
number string | 否 | WGS-84,可选 |
{
"line": {
"lineId": "21283603183", "name": "71", "lineNo": "r95817", "direction": 0,
"startSn": "延安东路外滩", "endSn": "申昆路枢纽站",
"firstTime": "05:30", "lastTime": "23:30", "price": "2元", "stationsNum": 24
},
"stations": [
{ "order": 1, "sId": "...", "sn": "延安东路外滩", "wgsLat": 31.23, "wgsLng": 121.49, "physicalStId": "...", "namesakeStId": "...", "metros": [] }
],
"buses": [
{ "busId": "...", "order": 2, "lat": 31.23, "lng": 121.47, "speed": 5.7, "capacity": 0 }
],
"reverseDirection": {
"lineId": "21283603182", "startSn": "申昆路枢纽站", "endSn": "延安东路外滩",
"firstTime": "04:30", "lastTime": "22:30", "price": "2元"
},
"depDesc": "...", "preArrivalTime": "...", "targetOrder": 24
}地铁线路返回 empty: true 与 hint,不要重试,改用 /v1/stops/detail 或 /v1/transit/plan。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
line_id |
string | 是 | 线路 ID |
include_shape |
boolean | false |
false 仅站点标记(约 25 点);true 全部形状点(约 400–500 点) |
{ "pointCount": 480, "stopCount": 23, "points": [{ "lat": 31.23, "lng": 121.49, "stopOrder": 1 }] }| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
line_id |
string | 是 | 线路 ID |
target_order |
integer string | 是 | 等待站点在线路上的序号 |
station_id |
string | 是 | 等待站点的 sId
|
lat / lng
|
number string | 是 | WGS-84;不知道用户位置时可用站点坐标 |
{
"line": { "lineId": "21283603183", "name": "71", "direction": 0, "endSn": "申昆路枢纽站" },
"targetOrder": 2,
"realData": true,
"buses": [
{ "busId": "...", "licence": "沪A12345", "order": 2, "lat": 31.23, "lng": 121.47, "speed": 5.7, "capacity": 0, "distanceToWaitStn": 90,
"eta": { "travelTime": 25, "arrivalTime": 1779070466055, "displayTime": "10:14" } },
{ "busId": "...", "order": 3, "lat": 31.24, "lng": 121.46, "speed": 3, "capacity": 0, "eta": null }
],
"note": "..."
}上游只为最近一辆驶向目标站的车辆计算 eta,其余车辆 eta: null 属正常。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id / line_id
|
string | 是 | 城市 / 线路 ID |
target_order |
integer string | 是 | 等待站点序号 |
station_name |
string | 是 | 等待站点名称 |
{
"targetOrder": 2,
"buses": [
{ "busId": "...", "licence": "沪A12345", "order": 2, "lat": 31.23, "lng": 121.47, "speed": 8.2, "capacity": 0,
"nextStop": "西藏中路", "eta": { "travelTime": 214, "arrivalTime": 1779070686000, "displayTime": "10:18" } }
]
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id / line_id
|
string | 是 | 城市 / 线路 ID |
line_no |
string | 是 | 面向乘客的短名(search.lines[].name,如 71),不是 r95817
|
direction |
"0" | "1" |
是 | 方向 |
{
"line": { "lineId": "21283603183", "name": "71", "direction": 0, "startSn": "...", "endSn": "..." },
"timeTableType": 2,
"mode": "interval",
"timetable": null,
"note": "This line runs at a fixed interval — ..."
}mode:scheduled(逐班时刻)、interval(固定间隔)、special、unknown。
查首末班请优先用 /v1/lines/detail。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
line_stn |
string | 是 | 四元组 lineId,stopId,nextId,targetOrder,多条以 ; 分隔(nextId 可空,建议 ≤10 条) |
curl "https://ts-api.tundrey.com/v1/lines/refresh?city_id=034&line_stn=21283603183,021-15232,,2;21283604388,021-8685,,4"{
"lines": [
{
"line": { "lineId": "21283603183", "name": "71", "direction": 0, "endSn": "申昆路枢纽站" },
"depDesc": "10分钟后发车",
"buses": [{ "busId": "...", "order": 2, "capacity": 0, "distanceToDest": 881, "eta": { "travelTime": 221, "arrivalTime": 1779070466055 } }]
}
]
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
city_id |
string | 是 | 城市 ID |
origin_name / dest_name
|
string | 是 | 起点 / 终点名称(展示用) |
origin_lat / origin_lng
|
number string | 是 | 起点坐标,GCJ-02 |
dest_lat / dest_lng
|
number string | 是 | 终点坐标,GCJ-02 |
strategy |
"0" | "1" | "2" | "3" |
否 |
0 推荐(默认,含地铁)、1 少换乘、2 少步行、3 最短时间(上游常排除地铁) |
{
"origin": "121.49073,31.233021",
"destination": "121.327,31.197",
"distance": 17982,
"plans": [
{
"duration": 3056, "walkingDistance": 1466, "distance": 19086, "tag": "直达", "transitCount": 1,
"segments": [
{ "type": "walking", "distance": 837, "duration": 717 },
{ "type": "bus", "name": "地铁2号线", "lineType": 1, "departureStop": "人民广场", "arrivalStop": "虹桥2号航站楼",
"viaStops": 8, "duration": 1800, "distance": 17620, "startTime": "05:37", "endTime": "23:30" }
]
}
]
}lineType:0 公交、1 地铁。