星课程表的开放 API 让你的脚本、第三方插件或自动化工具能用 HTTP 请求读取自己的课表、备忘录和课堂笔记,也可以在获得伙伴关系授权后查询伙伴的固定课表并比对共同空闲时间。 鉴权基于「应用密码」 —— 在「我的 → 开放 API」生成,可独立删除 / 旋转,不影响登录密码。
用户名 = 你的星 ID,密码 = 在网页 / App 生成的应用密码。
一个帐号最多 5 个,随时旋转 / 删除,旧密码立刻失效。
只读取已接受伙伴关系,伙伴课表仅限对方当前固定课表。
单密码每分钟 60 次,超出返 429。
所有 /v1/open/* 接口都要求带 HTTP Basic Auth:
Authorization: Basic base64("星ID:应用密码")`curl` 直接传 `-u` 参数会自动完成 base64 编码:
curl -u "你的星ID:你的应用密码" \ https://starschedule.xingqingchuang.com/api/v1/open/schedules
鉴权失败统一返 401 + { code: 401, message, data: null },响应头带 WWW-Authenticate: Basic。备忘录、课堂笔记、伙伴课表和空闲时间接口使用同一个应用密码即可访问,数据范围始终限定在当前帐号自己的数据(伙伴数据仅限已接受的伙伴关系)。
应用密码默认带 read 权限,覆盖所有读取接口。勾选写入权限后可新建、修改、删除备忘录、待办和笔记;只读密码写入会被拒绝(403)。
read — 读取你自己的课表、备忘录、笔记、成绩与校园数据。write:daily — 另外可以新建、修改、删除你的备忘录、待办和课堂笔记。下面每个接口都由服务端自己的函数注册表生成 OpenAPI 3.1 描述,不会与实现脱节。可以直接把客户端生成器指向它,也可以自己阅读。
openapi.json/v1/open/schedules{
"code": 0,
"message": "ok",
"data": {
"schedules": [
{ "uid": "abcd1234...", "name": "2025 春季" },
{ "uid": "efgh5678...", "name": "实习课表" }
]
}
}/v1/open/schedules/{uid}include(query)— 逗号分隔的子段。可选 courses / adjustments / exams / clubs。不传 = 全部。uid(path)— 上一接口里返回的 schedule uid。{
"code": 0,
"message": "ok",
"data": {
"schedule": {
"uid": "abcd1234...",
"name": "2025 春季",
"term": {
"uid": "term-...",
"name": "2024-2025 第二学期",
"startDate": "2025-02-24",
"totalWeeks": 18
},
"courses": [ /* course_uid, name, color, credit, note ... */ ],
"courseSessions": [ /* weekday, start/end section, start/end week, location, teacher ... */ ],
"temporaryAdjustments": [ /* 停课 / 换时间 / 换地点 */ ],
"exams": [ /* 考试日程 */ ],
"clubActivities": [ /* 社团活动 */ ]
},
"meta": { "include": ["adjustments", "clubs", "courses", "exams"] }
}
}/v1/open/memosfrom / to(query)— 按日期筛选,格式为 YYYY-MM-DD。updatedSince(query)— 只返回此时间之后更新的记录,便于增量同步。todo(query)— 可选 true / false,按待办状态筛选。{
"code": 0,
"message": "ok",
"data": {
"items": [
{
"uid": "memo-uid",
"date": "2025-03-12",
"content": "提交实验报告",
"color": "#4F46E5",
"isTodo": true,
"completedAt": null,
"deadlineAt": "2025-03-15T23:59:00+08:00",
"reminderAt": null,
"createdAt": "2025-03-01T08:00:00Z",
"updatedAt": "2025-03-12T10:00:00Z"
}
],
"nextCursor": null
}
}/v1/open/class-notesscheduleUid / courseUid / sessionUid(query)— 可选的课表、课程和课次 UID。只能读取当前帐号自己的数据。occurrenceDate(query)— 按课堂发生日期筛选,格式为 YYYY-MM-DD。include(query)— 可选 assets,topic。assets 返回图片资产元数据(uid / mimeType / sort);图片文件下载暂不通过开放 API 提供。{
"code": 0,
"message": "ok",
"data": {
"items": [
{
"uid": "note-uid",
"scheduleUid": "schedule-uid",
"courseUid": "course-uid",
"sessionUid": "session-uid",
"occurrenceDate": "2025-03-12",
"content": "老师强调了递归边界条件。",
"topic": "算法基础",
"createdAt": "2025-03-12T15:30:00Z",
"updatedAt": "2025-03-12T15:40:00Z",
"assets": []
}
],
"nextCursor": null
}
}/v1/open/buddies{
"code": 0,
"message": "ok",
"data": {
"items": [
{
"linkId": "buddy-link-uid",
"peer": {
"sid": "ABC12345",
"nickname": "小明",
"school": "某某大学",
"avatarUrl": null
},
"state": "accepted",
"hasPinnedSchedule": true,
"updatedAt": "2025-03-09T17:30:00Z"
}
],
"nextCursor": null
}
}/v1/open/buddies/{linkId}/schedulelinkId(path)— 伙伴列表返回的关系 ID,关系必须属于当前帐号且状态为 accepted。{
"code": 0,
"message": "ok",
"data": {
"buddy": {
"linkId": "buddy-link-uid",
"sid": "ABC12345",
"nickname": "小明"
},
"pinnedSchedule": {
"uid": "schedule-uid",
"name": "2025 春季",
"term": {
"name": "2024-2025 第二学期",
"startDate": "2025-02-24",
"totalWeeks": 18
},
"courses": [ /* 课程和上课节次 */ ],
"temporaryAdjustments": [ /* 停课 / 换时间 / 换地点 */ ],
"timeScheme": { "sections": [ /* 节次时间 */ ] }
}
}
}/v1/open/free-time/compareselfScheduleUid(body)— 当前帐号自己的课表 UID。linkIds(body)— 伙伴关系 ID 列表。服务端自动读取每位伙伴的固定课表,不能传入伙伴 scheduleUid。dateFrom / dateTo(body)— 日期范围,最长 31 天。{
"code": 0,
"message": "ok",
"data": {
"basis": "section",
"timezone": "Asia/Shanghai",
"participantCount": 2,
"slots": [
{
"date": "2025-03-10",
"weekday": 1,
"week": 3,
"startSection": 3,
"endSection": 4,
"startTime": "10:10",
"endTime": "11:50",
"durationMinutes": 100
}
],
"warnings": []
}
}伙伴接口只允许访问已接受关系。 伙伴课表始终由服务端从对方当前的固定课表解析,不能查询对方其他课表。 空闲时间接口只返回所有参与人的共同空闲时段,不返回谁在什么时候有课、课程名称、教师或地点。 伙伴尚未设置固定课表时,不会使用其他课表代替,接口会跳过该伙伴并在 warnings 中说明。
GET /v1/open/meGET /v1/open/schedulesGET /v1/open/schedules/{uid}GET /v1/open/schedules/{uid}/coursesGET /v1/open/schedules/{uid}/time-schemeGET /v1/open/schedules/{uid}/adjustmentsGET /v1/open/schedules/{uid}/examsGET /v1/open/schedules/{uid}/clubsGET /v1/open/termsGET /v1/open/timetable/currentGET /v1/open/timetable/occurrencesGET /v1/open/examsGET /v1/open/club-activitiesGET /v1/open/memosGET /v1/open/todosGET /v1/open/class-notesGET /v1/open/campusGET /v1/open/campus/gradesGET /v1/open/campus/attendanceGET /v1/open/campus/seatsGET /v1/open/snapshot/summaryGET /v1/open/snapshotGET /v1/open/buddiesGET /v1/open/buddies/{linkId}/schedulePOST /v1/open/free-time/comparePOST /v1/open/memosPATCH /v1/open/memos/{uid}DELETE /v1/open/memos/{uid}POST /v1/open/todosPATCH /v1/open/todos/{uid}POST /v1/open/todos/{uid}/completeDELETE /v1/open/todos/{uid}POST /v1/open/class-notesPATCH /v1/open/class-notes/{uid}DELETE /v1/open/class-notes/{uid}每个应用密码 60 次/分钟,滚动窗口。命中限速返 429 + { code: 429, message, data: null },响应头带 RateLimit-* 系列(draft-7)字段说明剩余配额。
如果需要更高频率(例如做面板轮询),建议本地缓存接口结果 + 用 Last-Modified 语义自己降频,而不是反复打 API。
| HTTP | code | 含义 |
|---|---|---|
| 401 | 401 | 未带凭据 / 星 ID 或密码错误 / 密码已被吊销 |
| 404 | 404 | 课表 uid 不存在或属于其他帐号 |
| 403 | 403 | 没有对应数据权限,或无权访问该伙伴关系 |
| 409 | 409 | 伙伴关系尚未接受(未建立联系);伙伴未设置固定课表时不会报错,而是返回 pinnedSchedule: null 或在比对结果 warnings 中说明 |
| 429 | 429 | 单密码超过 60 次/分钟 |
| 500 | 500 | 服务端读取课表失败,请稍后重试 |