群应用与群数据同步
阅读指引:本篇是《开放平台服务端 API 指南》的第 11 部分。接口基础地址、通用约定与各接口请求限制,请先阅读《服务端 API 概览》。
14. 群应用与群数据同步
群应用是“真实应用与某一个群之间的授权关系”。群主或群管理员在客户端把一个已发布、已获授 group:app 的真实应用添加到群后,该应用才可以读取该群的最小信息、同步成员,并以应用身份向该群发送消息。
Scope 与群关系必须同时成立有效 App Token 包含 group:app,只能证明应用具备群应用能力;目标群仍必须存在 active 绑定关系。应用实时 Scope 被撤销、应用不再是已发布状态或群关系被移除时,即使旧 Token 仍带有该 Scope,也不能继续访问。
14.1 能力边界与生命周期
- 群应用不是群成员,不出现在群成员列表、不占群人数,也没有群主或管理员角色。
- 应用只能读取本文明确列出的群 ID、名称、变化时间以及成员 ID、群内名称和角色;不能读取群聊历史、公告、头像、群设置或组织扩展信息。
- 应用不能修改群资料、邀请、移除或修改群成员,也不能自行添加到群、搜索或枚举未绑定群。
- 应用快捷方式不是独立应用身份,不能作为群应用添加;群关系绑定真实主应用 ID。
- Webhook 不是群应用的准入条件,只是变化加速通知;没有 Webhook 时仍可完整使用游标同步。
- 群主或管理员移除应用后,读取和发送权限立即失效。应用下架或删除会移除全部 active 群关系,且不保证再向已下架应用发送 removed Webhook;重新上架不会恢复,必须由各群重新添加。
- 暂停的部门群保留已有绑定,应用仍可读取和同步当前群数据,但不能发送应用群消息;恢复后原关系继续生效。
管理员授予应用 group:app
→ 群主/群管理员在客户端添加真实应用
→ 应用用 App Token 调用 groups/changes
→ 获取群信息并全量同步成员
→ 保存 next_cursor,持续增量同步
→ Webhook 到达时只负责唤醒同步
14.2 增量获取应用的群
GET /openapi/v1/groups/changes?cursor=&limit=
首次调用省略 cursor,平台按群 ID 分页返回当前所有 active 群。全量页读取结束后,继续保存并使用最后的 next_cursor,后续调用自动进入增量模式,返回新增、变化和已移除群。
curl "${OPENAPI_BASE_URL}/openapi/v1/groups/changes?limit=50" \
-H "Authorization: Bearer ${APP_ACCESS_TOKEN}"
{
"code": 200,
"message": "",
"data": {
"groups": [
{
"group_id": "20001",
"relation_version": 3,
"group_updated_at": 1789027000000,
"member_updated_at": 1789027200123
}
],
"removed_group_ids": [],
"next_cursor": "opaque_cursor",
"has_more": false
},
"request_id": "request_xxx"
}
| 字段 | 类型 | 含义 |
|---|---|---|
groups[].group_id |
string | 当前 active 绑定群 ID。 |
groups[].relation_version |
integer | 添加或移除关系版本;与本地记录不同应视为一次新授权,并重新全量同步成员。 |
groups[].group_updated_at |
integer | 群基本信息最后变化时间,Unix 毫秒;变化时重新获取群信息。 |
groups[].member_updated_at |
integer | 群成员基本信息最后变化时间,Unix 毫秒;变化时继续成员增量同步。 |
removed_group_ids |
string[] | 已经失效的群关系;停止该群任务并删除不再需要的本地群数据。 |
next_cursor |
string | 不透明游标;必须原样保存,不能解析、修改或跨应用复用。 |
has_more |
boolean | true 时立即使用本页 next_cursor 继续取下一页;false 时保存游标供下次轮询。 |
limit 省略时为 50,可填写 1~200。query 只能包含一个 cursor 和一个 limit;重复参数、未知参数、空或超限 limit 都返回无效请求。即使使用 Webhook,也应定期调用本接口兜底。
14.3 获取群基本信息
GET /openapi/v1/groups/info?group_id=
curl "${OPENAPI_BASE_URL}/openapi/v1/groups/info?group_id=20001" \
-H "Authorization: Bearer ${APP_ACCESS_TOKEN}"
{
"code": 200,
"message": "",
"data": {
"group_id": "20001",
"name": "产品研发群",
"group_updated_at": 1789027000000,
"member_updated_at": 1789027200123
},
"request_id": "request_xxx"
}
group_id 必须且只能出现一次,并使用十进制正整数字符串。接口只返回上述四个字段;群主通过成员接口的 role=owner 识别。群不存在、未绑定或关系已失效时统一返回 group_not_available,不会透露该群是否真实存在。
14.4 全量或增量获取群成员
GET /openapi/v1/groups/members?group_id=&cursor=&limit=
第一次同步某个群时省略 cursor,按用户 ID 分页获取全量成员;全量结束后继续保存最后的 next_cursor,后续调用进入增量模式。
{
"code": 200,
"message": "",
"data": {
"members": [
{"user_id": "9001", "name": "张三", "role": "admin"}
],
"removed_user_ids": ["9002"],
"next_cursor": "opaque_member_cursor",
"has_more": false,
"full_sync_required": false
},
"request_id": "request_xxx"
}
| 字段 | 类型 | 含义 |
|---|---|---|
members[].user_id |
string | 当前成员用户 ID。 |
members[].name |
string | 群内显示名称。 |
members[].role |
string | owner、admin 或 member。 |
removed_user_ids |
string[] | 增量阶段已移除的用户;从该群本地成员快照删除。 |
next_cursor |
string | 绑定当前应用、群和关系版本的不透明游标。 |
has_more |
boolean | true 时继续读取下一页。 |
full_sync_required |
boolean | true 表示关系版本变化或历史增量已不可连续读取;丢弃该群旧 cursor 和临时快照,从无 cursor 开始全量重建。 |
成员数据刻意收敛,不返回头像、手机号、邮箱、性别、备注、禁言、组织归属或部门群成员来源。limit 默认 50、最大 200;query 只允许 group_id/cursor/limit。
14.5 推荐同步算法
- 持久化应用级
groups_cursor,首次为空;循环调用groups/changes直到has_more=false。 - 对每个新增群或
relation_version变化的群,读取groups/info,清空旧成员 cursor,从无 cursor 开始全量成员同步。 - 仅
group_updated_at变化时重新读取群信息;member_updated_at变化时用该群已完成的成员 cursor 继续增量读取。 - 收到
removed_group_ids时立即停止访问并清理本地数据,不再调用该群 info/members。 - 成员响应
full_sync_required=true时,不提交旧 cursor 重试;必须重新全量构建临时快照,完成全部分页后再原子替换正式快照。 - 只有一页处理和本地提交都成功后才保存该页 next_cursor;失败时使用原 cursor 重试,避免漏数据。
14.6 HTTP 状态与错误码
| HTTP | code | message | 处理 |
|---|---|---|---|
| 400 | 170800 |
invalid_request |
修正 query、ID、limit 或游标;不要原样无限重试。 |
| 401/403 | Token/Scope 相关码 | 按鉴权响应 | 重新取得 App Token,或确认管理员仍授予 group:app。 |
| 404 | 170801 |
group_not_available |
群不存在、未绑定或关系已失效;停止该群任务并通过 changes 收敛。 |
| 409 | 170802 |
full_sync_required |
如果接口返回该兼容错误,丢弃旧游标并重新全量;成员接口成功响应中的同名布尔字段也按此处理。 |
| 503 | 170803 |
group_service_unavailable |
保留已完成快照和原 cursor,有限次数指数退避。 |
成员同步要求优先检查 full_sync_required:当前关系版本变化或增量历史不连续时,返回 HTTP 200、code=200、full_sync_required=true,此时 next_cursor 可为空。不要只等待 409。签名密钥轮换后旧游标会返回 400 / 170800;清空应用群列表游标及各群成员游标,从全量重新开始。
全量分页不是冻结快照;读完后保存游标并继续增量轮询以追平期间变化。群列表和各群成员分别维护游标,不能交叉使用。全量重建使用临时快照,完成后以新快照替换旧集合,不能只做新增合并,否则已移除对象会残留。
14.7 群主和管理员如何管理群应用
添加、查看和移除群应用是 Matrix 客户端登录态下的群管理能力,不是应用 OpenAPI。应用后端不能调用本文的 OpenAPI 把自己加入群,也不能取得“可添加群列表”。客户端侧遵循以下规则:
- 当前群成员可以获取该群完整的应用 ID 列表;应用详情复用客户端已有应用数据。
- 只有群主或群管理员可以添加、移除,一次操作一个真实应用 ID;用户身份和角色由服务端登录态判断。
- 添加时服务端校验应用已发布、未删除且实时具备
group:app;重复添加和重复移除按幂等语义处理。 - 管理操作成功不代表应用 Webhook 已送达。应用以
groups/changes返回的当前状态作为最终依据。