基础数据对接指南
本文说明如何通过希悦开放平台 API 从平台获取基础数据,用于对接外部系统。本文覆盖以下数据能力:
- 学年学期
- 用户数据(学生、教师)
- 组织架构(年级、学科组等)
- 班级数据(行政班、教学班)
- 教师任课(每个教师任教哪些班级)
- 班级与学生对应关系
本文仅覆盖数据读取场景,不包含写入、删除等变更操作。
1. 接口范围
| 接口能力 | 作用 | 在本指南中的用途 |
|---|---|---|
System |
获取学期列表、基础 term 字典 | 获取学年学期及学期类型 |
Reflection |
获取用户身份数据 | 获取学生、教师、家长等用户数据 |
AdminClass |
获取行政班数据 | 获取行政班及其学生、班主任 |
Klass |
获取教学班(课程班)数据 | 获取教学班、任课教师、班级成员 |
Structure |
获取架构列表与详情 | 获取学校架构(年级、学科组等) |
2. 对接前准备
2.1 鉴权
平台使用 OAuth 2.0 Client Credentials 模式获取 access_token。详见 docs/oauth.md。
Token 接口:
POST /api/v3/oauth/tokens
业务接口请求头:
Authorization: Bearer {access_token}
X-School-Id: {school_id}
要求:
Authorization用于传递访问令牌。X-School-Id按平台通用约定传递学校上下文。
2.2 权限范围(Scope)
各接口通过 OAuth Scope 鉴权,所需 Scope 如下:
| 接口 | 所需 Scope |
|---|---|
| 学期列表 | semester.read |
| 通用用户数据 | reflection.read_basic 或 reflection.read_all |
| 学生数据 | student.read_basic 或 student.read_all |
| 教师数据 | teacher.read_basic 或 teacher.read_all |
| 行政班数据 | admin_class.read |
| 教学班(课程班)数据 | class.read |
| 组织架构 | structure.read |
说明:
read_basic仅返回基础字段,read_all返回全部字段。按需选择最低授权范围。- 请在申请时按需开通,遵循最小授权原则。
2.3 分页与筛选约定
分页
集合类接口均支持 paginated、page、per_page 参数,分页响应头约定详见 docs/conventions.md。
| 参数 | 类型 | 说明 |
|---|---|---|
paginated |
integer |
是否分页,默认 1 |
page |
integer |
页码,默认 1 |
per_page |
integer |
每页数量,默认 20 |
关联展开(expand)
部分接口支持 expand 参数,用逗号分隔需要展开的关联资源,例如 expand=students,teachers。
增量同步
用户、班级、教学班、成员等接口支持 updated_at_egt(仅查询指定时间之后更新或新建的数据)与 with_trashed(是否包含软删除数据)参数,可用于实现增量同步,详见第 12 节。
3. 数据关系总览
semester(学年学期)
├── academic_year(学年)
├── category(学期类型)
└── is_current(是否当前学期)
admin_class(行政班)
├── teachers(班主任)
├── students(班级学生)
└── classes(关联的教学班)
class(教学班/课程班)
├── semester_id(所属学期)
├── teachers(任课教师)
├── students(班级学生)
└── admin_class_ids(关联的行政班)
reflection(用户身份)
├── student(学生)
├── teacher(教师)
└── guardian(家长)
关键关系:
- 一个
semester属于一个academic_year,属于一个学期类型category - 一个
admin_class下有多个学生students和多个班主任teachers - 一个
class属于一个semester,有多个任课教师teachers和多个学生students - 一个
class可关联多个admin_class,一个admin_class可关联多个class
4. 总体调用顺序
推荐调用顺序如下:
- 通过 OAuth 获取 Token
- 确认应用已开通所需 Scope
- 调用学期接口,确定目标学期
semester_id(优先使用is_current=true的当期学期) - 调用用户数据接口,全量或增量同步学生、教师
- 调用行政班接口,同步行政班及其学生、班主任
- 调用教学班接口,同步教学班及其任课教师、成员
- 调用架构接口,获取架构详情(年级、学科组等)
- 按需使用
updated_at_egt做增量更新
5. 获取学年学期
接口:
GET /v3/system/semesters
OpenAPI:获取学期列表
说明:
- 用于获取学年学期列表,是所有班级、教学班数据的挂载点。
- 使用
expand=academic_year展开学年,expand=category展开学期类型,expand=is_current标记是否当前学期。
请求参数:
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id_in |
query | string |
否 | 指定学期 ID,多个用逗号分隔 |
expand |
query | string |
否 | 支持 academic_year、category、is_current |
paginated |
query | integer |
否 | 是否分页,默认 1 |
page |
query | integer |
否 | 页码,默认 1 |
per_page |
query | integer |
否 | 每页数量,默认 20 |
返回字段(Semester):
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
id |
integer |
否 | 学期 ID |
school_id |
integer |
否 | 学校 ID |
academic_year_id |
integer |
否 | 学年 ID |
category_id |
integer |
否 | 学期类型 ID |
name |
string |
否 | 学期名 |
start_at |
string |
否 | 学期开始时间,格式 YYYY-MM-DD |
end_at |
string |
否 | 学期结束时间,格式 YYYY-MM-DD |
is_current |
boolean |
是 | 是否当前学期(需 expand) |
is_temporary |
boolean |
是 | 是否临时学期 |
current_week |
integer |
是 | 当前学期对应的当前周数 |
grade_maps |
object |
是 | 年级届别对应关系 |
outer_id |
string |
是 | 外部 ID |
同步建议:
- 优先使用
is_current=true的学期作为默认同步目标。 - 若需同步历史学期数据,按
id_in或循环逐学期拉取即可。
6. 获取用户数据
用户数据分为三类接口,均返回 Reflection 对象:
- 通用用户:
GET /v3/reflection/reflections(OpenAPI:获取用户数据) - 学生:
GET /v3/reflection/students(OpenAPI:获取学生数据) - 教师:
GET /v3/reflection/teachers(OpenAPI:获取教师数据)
说明:
reflections接口通过role参数可筛选teacher、student、guardian。students、teachers接口为按角色定向获取,参数更细化。- 三者返回的
Reflection.id即用户在班级成员、任课关系中的reflection_id,是跨接口关联的关键。
请求参数:
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
role |
query | string |
否 | 仅 reflections 接口,可选 teacher、student、guardian |
id_in |
query | string |
否 | 仅 students/teachers 接口,指定用户 ID,多个用逗号分隔 |
name_in |
query | string |
否 | 仅 students/teachers 接口,按姓名精确检索,多个逗号分隔 |
name_like |
query | string |
否 | 仅 students/teachers 接口,按姓名模糊检索 |
phone |
query | string |
否 | 按手机号检索 |
sort |
query | string |
否 | 排序字段,前缀 - 表示倒序 |
updated_at_egt |
query | string |
否 | 增量时间,格式 YYYY-MM-DD HH:MM:SS |
with_trashed |
query | boolean |
否 | 是否包含软删除记录 |
expand |
query | string |
否 | reflections 支持 archived_type;students 支持 graduates_in、grade、archived_type;teachers 支持 discipline、archived_type、department_names |
返回字段(Reflection):
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
id |
integer |
否 | 用户身份 ID(主键) |
school_id |
integer |
否 | 学校 ID |
name |
string |
否 | 姓名 |
role |
string |
否 | 角色:teacher、student、guardian、staff、shadow |
usin |
string |
是 | 学工号 |
gender |
string |
是 | 性别:m - 男,f - 女 |
phone |
string |
是 | 手机号码 |
email |
string |
是 | 电子邮箱 |
idcard |
string |
是 | 身份证号 |
photo |
string |
是 | 头像 |
status |
string |
否 | 状态:normal - 正常,archived - 归档 |
structure_ids |
array<integer> |
是 | 架构 ID 列表 |
graduates_in_id |
integer |
是 | 届别 ID |
outer_id |
string |
是 | 外部系统 ID |
deleted_at |
string |
是 | 数据删除时间 |
7. 获取组织架构
接口:
GET /v3/structure/structures
OpenAPI:获取组织架构列表
说明:
- 架构是学校基于年级、学科组等维度建立的层级结构,行政班、教学班、用户均通过
structure_ids关联到架构。 - 通过
expand=parent展开父级架构,expand=children展开子级架构,expand=managers展开管理员列表。 - 通过
type可按架构类型筛选,通过parent_id可获取指定父级下的子级架构。
请求参数:
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
type |
query | string |
否 | 架构类型:headquarters、campus、school_level、grade、subject_group |
status |
query | string |
否 | 状态:normal、archived |
parent_id |
query | integer |
否 | 父级架构 ID |
expand |
query | string |
否 | 支持 parent、children、managers |
sort |
query | string |
否 | 排序字段,前缀 - 表示倒序 |
fields |
query | string |
否 | 返回字段,多个用逗号分隔 |
paginated |
query | integer |
否 | 是否分页,默认 1 |
page |
query | integer |
否 | 页码,默认 1 |
per_page |
query | integer |
否 | 每页数量,默认 20 |
返回字段(Structure,数组):
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
id |
integer |
否 | 架构 ID |
school_id |
integer |
否 | 学校 ID |
name |
string |
否 | 结构名称 |
type |
string |
否 | 结构类型:headquarters、campus、school_level、grade、subject_group |
path |
string |
否 | 结构路径 |
depth |
integer |
否 | 结构深度 |
seq |
integer |
否 | 序号 |
weight |
integer |
否 | 排序权重 |
status |
string |
否 | 状态:normal、archived |
subject_ids |
array<integer> |
是 | 科目 ID 列表 |
manager_ids |
array<integer> |
是 | 管理员用户 ID 列表 |
parent |
object |
是 | 父级结构(需 expand) |
children |
array<object> |
是 | 子级结构(需 expand) |
managers |
array<object> |
是 | 管理员列表(需 expand) |
outer_id |
string |
是 | 外部系统 ID |
补充说明:
- 如需获取整个架构树,可先拉取列表,再通过
expand=children或按parent_id逐层展开。 - 如需获取单个架构的详情,可调用
GET /v3/structure/structures/{id}(OpenAPI:获取架构详情)。 - 架构类型
type主要用于区分校区、学段、年级、学科组等层级。
8. 获取班级数据
8.1 行政班
接口:
GET /v3/admin_class/admin_classes
OpenAPI:获取行政班接口
说明:
- 行政班是学校按年级、班级划分的固定班制单位。
- 通过
expand=students获取班级学生,expand=teachers获取班主任,expand=classes获取关联的教学班。 status为archived时表示历史行政班(已归档),同步时应过滤,仅保留status=normal的行政班。
请求参数:
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id |
query | integer |
否 | 行政班 ID |
id_in |
query | string |
否 | 行政班 ID 列表,逗号分隔 |
name_like |
query | string |
否 | 名称模糊搜索 |
name_in |
query | string |
否 | 名称精确搜索,逗号分隔 |
teacher_id |
query | integer |
否 | 教师 ID,即 reflection_id |
place_id |
query | integer |
否 | 空间 ID |
status |
query | string |
否 | 状态:normal、archived |
outer_id |
query | string |
否 | 外部 ID |
outer_id_in |
query | string |
否 | 外部 ID 列表,多个用逗号分隔 |
expand |
query | string |
否 | 支持 students、teachers、classes、structures |
返回字段(AdminClass):
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
id |
integer |
否 | 行政班 ID |
school_id |
integer |
否 | 学校 ID |
name |
string |
否 | 行政班名称 |
graduates_in_id |
integer |
否 | 届别 Term ID |
place_id |
integer |
是 | 教室 ID |
student_nums |
integer |
否 | 学生数量 |
status |
string |
否 | 状态:normal - 正常,archived - 归档(历史行政班,需过滤) |
teacher_ids |
array<integer> |
是 | 班主任 ID 列表 |
teachers |
array<Reflection> |
是 | 班主任列表(需 expand) |
students |
array<AdminClassMember> |
是 | 学生列表(需 expand) |
classes |
array<ClassRelation> |
是 | 关联的教学班(需 expand) |
outer_id |
string |
是 | 外部 ID |
8.2 教学班(课程班)
教学班数据包含教学班列表与教学班成员两部分。
教学班列表
接口:
GET /v3/klass/classes
OpenAPI:获取课程班列表
说明:
- 教学班(课程班)隶属于某个学期,是选课走班后的授课单位。
- 推荐按
semester_id拉取指定学期的教学班。 - 通过
expand=teachers获取任课教师,expand=students获取班级学生,expand=admin_class_ids获取关联的行政班。
请求参数:
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id_in |
query | string |
否 | 指定教学班 ID,多个逗号分隔 |
semester_id |
query | integer |
否 | 学期 ID |
admin_class_id |
query | integer |
否 | 行政班 ID |
updated_at_egt |
query | string |
否 | 增量时间,格式 YYYY-MM-DD HH:MM:SS |
with_trashed |
query | integer |
否 | 是否包含已删除数据 |
expand |
query | string |
否 | 支持 teachers、students、class_lessons、places、grades、structures、subject、domain、admin_class_ids 等 |
返回字段(Class):
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
id |
integer |
否 | 教学班 ID |
school_id |
integer |
否 | 学校 ID |
semester_id |
integer |
否 | 学期 ID |
class_name |
string |
否 | 课程班名称 |
name |
string |
否 | 名称 |
subject_id |
integer |
是 | 科目 ID(term id, type=course.subject) |
domain_id |
integer |
是 | 领域 ID(term id, type=course.domain) |
teachers |
array<ClassSelection> |
是 | 任课教师(需 expand) |
students |
array<ClassSelection> |
是 | 班级学生(需 expand) |
admin_class_ids |
array<integer> |
是 | 关联的行政班 ID(需 expand) |
capacity |
integer |
是 | 容量 |
updated_at |
string |
否 | 更新时间 |
教学班成员
接口:
GET /v3/klass/class-selections
OpenAPI:获取课程班成员
说明:
- 教学班成员接口通过
class_id_in指定一个或多个教学班,返回这些教学班的成员,type区分成员类型,type=teacher为任课教师,type=student为班级学生。 - 必须指定
semester_id。 - 每个成员包含
class_id标识所属教学班,class_id与reflection_id组合即构成“用户属于哪些教学班”的映射。
请求参数:
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
semester_id |
query | integer |
是 | 学期 ID |
type |
query | string |
否 | 成员类型:teacher、student,默认 student |
class_id_in |
query | string |
否 | 指定教学班 ID,多个逗号分隔 |
updated_at_egt |
query | string |
否 | 增量时间,格式 YYYY-MM-DD HH:MM:SS |
with_trashed |
query | integer |
否 | 是否包含已删除数据 |
返回字段(ClassSelection):
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
class_id |
integer |
否 | 教学班 ID |
reflection_id |
integer |
否 | 用户身份 ID |
type |
string |
否 | 成员类型:teacher、student |
class_together |
boolean |
是 | 是否可以同时上多节课 |
created_at |
string |
否 | 创建时间 |
updated_at |
string |
否 | 更新时间 |
deleted_at |
string |
是 | 删除时间,未删除为 null |
9. 获取教师任课
教师任课关系指每个教师任教哪些班级。有两种方式:
方式一:教学班列表展开任课教师(推荐)
调用 GET /v3/klass/classes 并传 expand=teachers,返回的每个 Class 自带 id 与 teachers 数组(成员含 class_id、reflection_id),type=teacher 的成员即为该教学班的任课教师。可直接按 Class.id 得到每个班级的任课教师,适合需要一并获取班级属性的场景。
方式二:教学班成员接口
通过教学班成员接口按 type=teacher 获取,接口定义详见 §8.2 教学班成员。返回的成员含 class_id,按 class_id 分组即可得到每个教师任教的班级列表。
同步建议:
- 若需构建“教师 → 任教班级列表”映射,推荐使用 §8.2 教学班列表的
expand=teachers,按Class.id与teachers[].reflection_id组合即可。 - 也可通过教学班成员接口按
type=teacher获取,按返回的class_id分组。
10. 获取班级与学生对应关系
10.1 行政班-学生
调用 GET /v3/admin_class/admin_classes 并传 expand=students,返回 students 数组(AdminClassMember),每个元素即行政班与学生的对应关系。
AdminClassMember 字段:
| 字段 | 类型 | 可为空 | 描述 |
|---|---|---|---|
class_id |
integer |
否 | 行政班 ID |
reflection_id |
integer |
否 | 学生 ID(Reflection.id) |
entered_at |
string |
否 | 进班时间 |
leaved_at |
string |
是 | 退班时间 |
status |
string |
否 | 状态:entered、leaved |
10.2 教学班-学生
推荐调用 GET /v3/klass/classes 传 expand=students,返回的每个 Class 自带 id,students 数组(成员含 class_id、reflection_id)即教学班与学生的对应关系。也可通过教学班成员接口按 type=student 获取(接口定义详见 §8.2 教学班成员),返回的成员含 class_id,class_id 与 reflection_id 组合即教学班与学生的对应关系。
10.3 行政班-教学班关联
- 行政班侧:
GET /v3/admin_class/admin_classes传expand=classes,返回ClassRelation(class_id、admin_class_id)。 - 教学班侧:
GET /v3/klass/classes传expand=admin_class_ids,返回admin_class_ids数组。
11. 增量同步机制
以下接口支持增量拉取,用于降低全量同步成本:
| 接口 | 增量参数 | 说明 |
|---|---|---|
| 用户数据 | updated_at_egt |
获取指定时间之后更新或新建的用户 |
| 行政班 | 无(按 outer_id 或全量) |
行政班数据量通常不大,可全量拉取 |
| 教学班 | updated_at_egt |
课程班属性变化会更新 updated_at |
| 教学班成员 | updated_at_egt |
成员增删会更新 updated_at |
增量同步建议:
- 首次全量拉取,记录时间戳
last_sync_at。 - 后续传入
updated_at_egt={last_sync_at}拉取增量。 - 配合
with_trashed=1获取软删除数据,用于同步删除标记。 - 每次同步成功后更新
last_sync_at为本次拉取到的最大updated_at。