Zulip REST API 端点全景指南:从消息收发到实时事件队列的完整 API 地图
【免费下载链接】zulipZulip server and web application. Open-source team chat that helps teams stay productive and focused.项目地址: https://gitcode.com/GitHub_Trending/zu/zulip
Zulip 的 REST API 是其 Web 应用、桌面客户端、移动端、机器人(bot)与集成脚本共同的交互底座,官方宣称"只要你能在 Zulip 里做的事,都能通过 REST API 完成"。本文以 rest-endpoints.md 这份官方端点索引为骨架,系统梳理 Zulip 当前公开的13 大分类、约 160 个 REST 端点,并结合 zulip.yaml(31,902 行 OpenAPI 定义,166 个 operationId)与zerver/views/下的真实视图实现,深入讲解各端点群的用途、关键参数与底层机制。读完本文,你将获得一张"按功能域组织"的完整 API 地图,知道在什么场景该调用哪个端点、去哪个源文件验证行为,以及如何按官方规范为 Zulip 新增一个 API 端点。
这份索引文档的角色:API 文档的导航骨架
api_docs/include/rest-endpoints.md并不是一份普通的技术手册,而是 Zulip API 文档体系的索引文件(index):它按功能域把全部端点分成若干分类,每个条目是一个指向该端点独立文档页的链接。它的实际用途体现在两处:
- rest.md 第 28 行通过 Markdown include 语法
{!rest-endpoints.md!}将该索引嵌入《The Zulip REST API》总览页,成为所有端点的统一入口; - sidebar_index.md 同样以
{!rest-endpoints.md!}引入它,驱动 API 文档侧边栏的渲染。
也就是说,你看到的所有端点列表、侧边栏目录,都源于这一个文件。它的链接约定是:链接 URL(如/api/send-message)必须与端点在 OpenAPI 定义中的operationId完全一致,链接文本必须与 OpenAPI 的summary字段一致——这条规则在 docs/documentation/api.md 第 339-342 行有明确记载:
Add the endpoint to the index in
api_docs/include/rest-endpoints.md. The URL should match theoperationIdfor the endpoint, and the link text should match the title of the endpoint from the OpenAPIsummaryfield.
因此,这份文档与zerver/openapi/zulip.yaml是一一对应的:索引负责"导航",OpenAPI 定义负责"细节"。单个端点页的详细内容(Usage examples、Parameters、Response)则由 api-doc-template.md 定义的模板自动生成,本文末尾会专门拆解这个模板。
Messages:消息生命周期全链路
"消息"是 Zulip 的核心实体,这一分类也是端点最密集、被官方客户端使用最多的域。/messages端点在 zulip.yaml 中定义,其 GET 视图实现在 message_fetch.py 的get_messages_backend,POST 实现在 message_send.py 的send_message_backend,PATCH 实现在 message_edit.py 的update_message_backend。
| 端点(链接 = operationId) | 功能要点 |
|---|---|
| Send a message | 发送消息到频道或私聊,支持type(stream/private)、to、topic、content等参数 |
| Upload a file | 上传文件生成附件,返回uri供消息引用 |
| Edit a message | 修改消息内容;行为受"可编辑时间窗"等组织策略约束 |
| Delete a message | 删除消息(受组织权限与时间窗限制) |
| Get messages | 拉取消息的核心端点,配合 narrow 过滤器使用 |
| Construct a narrow | 构造窄化过滤器(按频道、话题、发送者、关键词等筛选消息) |
| Add / Remove an emoji reaction | 添加 / 移除表情回应 |
| Render a message | 服务端将 Markdown 渲染为 HTML,便于预览 |
| Fetch a single message | 按 ID 获取单条消息及其渲染内容 |
| Check if messages match a narrow | 判断一组消息是否匹配某个 narrow |
| Get a message's edit history | 获取消息编辑历史 |
| Update personal message flags / for narrow | 更新消息标记(已读、星标、话题关注等),后者针对窄化结果批量操作 |
| Mark all messages / channel / topic as read | 三种粒度的"标记已读" |
| Get a message's read receipts | 获取消息阅读回执 |
| Get temporary URL for an uploaded file | 为附件生成带时效的临时访问 URL |
| Check thumbnail status | 检查缩略图生成状态 |
| Report a message | 向服务端上报消息(用于滥用举报等) |
Get messages 与 narrow:拉取消息的正确姿势
GET /api/v1/messages在 OpenAPI 中的description指出:它是所有官方 Zulip 客户端(Web、桌面、移动、终端)以及大量机器人、备份脚本拉取消息的主要途径。其核心设计是"以锚点(anchor)为中心的窗口拉取":
anchor:整数消息 ID,也支持特殊字符串值newest(最新消息)、oldest(最旧消息)、first_unread(第一条未读消息,若无则取最新)、date(配合anchor_date取该时间点起的第一条消息,Zulip 12.0 / feature level 445 新增);num_before/num_after:分别指定锚点之前、之后各取多少条,二者至少提供一个;include_anchor:是否包含锚点消息本身,默认true(Zulip 6.0 / feature level 155 起提供);- 批量大小建议不超过 1000 条,单请求硬上限 5000 条,超出会报错——这是 zulip.yaml 中明示的官方建议。
message_ids变体(客户端显式指定要拉取的消息 ID 列表)是 Zulip 10.0 / feature level 300 新增的少见用法。用户的消息历史默认不含订阅频道之前的历史消息,且新建的机器人用户通常不订阅任何频道,这两点很容易被 API 初学者忽视。
Scheduled messages 与 Message reminders:时间维度的消息控制
| 端点 | 功能要点 |
|---|---|
| Get / Create / Edit / Delete a scheduled message | 定时消息的增删改查。创建端点在 create-scheduled-message.md 有独立文档,核心参数为scheduled_delivery_timestamp(Unix 时间戳),配合消息本身的内容与目标参数 |
| Create a message reminder | 为自己创建一条消息提醒 |
| Get / Delete reminders | 查询 / 删除已创建的提醒 |
定时消息适合"延迟发送"与"提醒型"工作流(例如晚间撰写、次日早晨触达);提醒则与消息内容解耦,是面向个人的时间管理能力。这两组端点让 Zulip API 在"消息发送"之外具备了完整的时间调度语义。
Drafts 与 Saved snippets:草稿与复用片段
| 端点 | 功能要点 |
|---|---|
| Get / Create / Edit / Delete a draft | 草稿的增删改查;草稿对象包含type、to、topic、content等字段,供客户端实现"自动保存草稿、跨设备同步" |
| Get / Create / Edit / Delete a saved snippet | 保存的消息片段(可复用的消息模板)的增删改查 |
草稿端点组支撑了 Zulip Web 客户端"写消息时自动保存草稿、重新打开时恢复"的体验;snippet 端点则进一步把常用消息内容(如团队公告模板、例行周报格式)沉淀为可复用资源。
Navigation views:组织内导航视图
| 端点 | 功能要点 |
|---|---|
| Get all navigation views | 获取组织内全部导航视图配置 |
| Add / Update / Remove a navigation view | 导航视图的增改删 |
导航视图(navigation view)是 Zulip 为组织定制客户端左侧导航结构的能力,属于偏组织级定制化的端点群。
Channels:频道全生命周期管理
这一分类对应 Zulip 模型中的"stream/channel"(新版文档统称 channel)。GET/POST /users/me/subscriptions定义在 zulip.yaml,/streams系列定义在第 24445 行。频道端点覆盖了"订阅关系—频道元数据—话题—默认频道—频道文件夹"五个层次:
| 端点 | 功能要点 |
|---|---|
| Get subscribed channels | 获取当前用户已订阅的频道(含Subscription对象数组) |
| Subscribe to a channel | 订阅一个或多个用户到频道;频道不存在时自动创建,可通过参数指定初始设置(如invite_only) |
| Unsubscribe from a channel | 退订频道 |
| Get subscription status | 查询单频道订阅状态 |
| Get channel subscribers / Get a user's subscribed channels | 按频道查订阅者 / 按用户查其订阅的频道 |
| Update a subscription setting / Bulk update | 单个 / 批量更新订阅偏好(通知方式、置顶、静音等) |
| Get all channels / Get a channel by ID / Get channel ID | 频道列表、按 ID 查、按名称查 ID |
| Create / Update / Archive a channel | 频道的创建、更新、归档 |
| Get channel's email address | 获取频道专属邮件地址(用于邮件网关发信) |
| Get topics in a channel | 列出频道内话题及最新消息时间 |
| Topic muting / Update personal preferences for a topic | 话题静音 / 更新个人对话题的偏好 |
| Delete a topic | 删除整个话题(连带其全部消息) |
| Add / Remove a default channel | 把频道设为 / 移出"新用户默认订阅频道" |
| Create / Get / Reorder / Update a channel folder | 频道文件夹的创建、查询、排序、更新 |
Subscribe 端点的权限演进(源码级佐证)
POST /users/me/subscriptions的 OpenAPI 描述记录了一段很有意思的权限演进史(zulip.yaml):
- Zulip 10.0(feature level 362)之前,已归档频道中的订阅关系不可修改;
- feature level 357 引入
can_subscribe_group权限,允许组成员自行订阅; - feature level 349 放宽了"订阅私有频道必须先订阅该频道"的限制:只要用户属于
can_add_subscribers_group,即使本人未订阅也可把他人加入私有频道; - feature level 333 移除了
stream_post_policy、is_announcement_only参数,发帖权限统一由can_send_message_group控制; - feature level 208 起,对不存在的/已停用的
principals(被操作对象),错误码从 403UNAUTHORIZED_PRINCIPAL改为 400BAD_REQUEST。
这提醒 API 使用者:订阅端点不是简单的"写库",其行为深度绑定组织的权限体系(Group 模型)。GET /users/me/subscriptions的响应中Subscription对象包含color、is_muted、pin_to_top、desktop_notifications、audible_notifications、push_notifications、invite_only、is_archived、creator_id、subscribers(订阅者 ID 列表)等字段,并且 Zulip 8.0 起响应中已移除email_address字段、Zulip 6.0 起移除role字段——字段的增删在 OpenAPI 里都有**Changes**标注,是查询"当前版本到底返回什么"的最权威来源。
Users:用户、状态、用户组与个性化
用户域是端点数量最多的分类之一(约 40 个),覆盖身份、状态、设置、用户组、机器人凭证五个子块:
| 端点 | 功能要点 |
|---|---|
| Get a user / by email / Get own user / Get users | 用户信息的四种查询方式(含include_custom_profile_fields等参数) |
| Create a user / Update a user / by email | 创建用户、按 ID 或邮箱更新用户 |
| Deactivate a user / own user / Reactivate | 停用他人 / 停用自己 / 重新激活 |
| Get a user's status / Update your status / Update user status | 用户状态(emoji + 状态文案)的查询与更新 |
| Update / Remove your profile data | 自定义档案字段(profile data)的增删 |
| Upload / Delete your profile picture | 头像上传与删除 |
| Set "typing" status / for message editing | 输入状态广播(两种场景:正在写消息 / 正在编辑消息) |
| Get a user's presence / Get presence of all users / Update your presence | 在线状态(presence)的三端点,配合客户端"在线显示" |
| Get / Delete attachments | 当前用户的附件列表与删除 |
| Update settings | 更新个人设置(通知偏好、显示偏好等,参数极多) |
| Get / Create / Update / Deactivate a user group | 用户组的增删改查(支持子组) |
| Update user group members / subgroups | 组成员增删、子组关系调整 |
| Get user group membership status / members / subgroups | 组成员关系查询 |
| Mute / Unmute a user | 静音 / 取消静音某个用户 |
| Get / Add / Remove alert words | 提醒词(alert word)管理 |
| Regenerate your API key / Get a bot's API key / Regenerate a bot's API key | 用户本人 / 机器人的 API key 管理与轮换 |
其中Get users端点支持按include_custom_profile_fields附带自定义档案字段,Update settings是"个人设置"的统一入口——Zulip 把大量用户级设置收敛到这一个端点,通过数百个可选参数实现;而组织级默认值则由 Server & organizations 分类中的Update realm-level defaults of user settings统一管控,二者形成"个人覆盖 / 组织兜底"的双层设置体系。
Invitations:邀请与可复用链接
| 端点 | 功能要点 |
|---|---|
| Get all invitations | 列出全部待处理邀请 |
| Send invitations | 发送邮箱邀请(可带invite_expires_in_minutes等参数) |
| Create a reusable invitation link | 生成可重复使用的邀请链接(适合社区型组织) |
| Resend / Revoke an email invitation | 重发 / 撤销邮箱邀请 |
| Revoke a reusable invitation link | 撤销可复用邀请链接 |
这组端点对应 Zulip 组织"邀请成员"的管理工作流,其中"可复用邀请链接"与"一次性邀请"在生命周期管理上做了明确区分。
Server & organizations:组织级配置与治理
这一分类是组织管理员视角的端点群(约 29 个),覆盖链接解析、自定义 emoji、档案字段、域名、数据导出、会话与会话体系等:
| 端点 | 功能要点 |
|---|---|
| Get server settings | 获取服务器设置(登录方式、功能开关等),客户端据此渲染 UI |
| Get / Add / Update / Remove / Reorder linkifiers | 链接解析器(把模式匹配的 URL 转成富文本链接)的增删改查与排序 |
| Add / Remove a code playground | 代码演练场(把代码块链接到外部 IDE/沙箱)的注册与移除 |
| Get all / Upload / Deactivate custom emoji | 自定义 emoji 的查询、上传、停用 |
| Get all / Reorder / Create / Update / Delete a custom profile field | 自定义档案字段的全生命周期管理 |
| Update realm-level defaults of user settings | 更新组织级用户设置默认值 |
| Get / Add / Update / Remove an allowed domain | 组织允许登录域名的管理 |
| Get all / Create a data export / Get export consent / Delete a data export | 数据导出工作流(含用户同意状态查询) |
| Test welcome bot custom message | 测试欢迎机器人自定义消息 |
| Deactivate an organization | 停用整个组织 |
其中"自定义档案字段"端点组与 Users 域的"Update your profile data"呼应:组织定义字段 schema,用户填充字段值,是组织定制化数据模型的标准做法。数据导出相关端点则支撑了 Zulip 的"GDPR 式数据可携带"能力。
Real-time events:实时事件队列系统
这是 Zulip API 中最具特色的部分,也是其"类 IRC + 类 Slack"实时体验的引擎。四个端点构成完整的"注册—拉取—确认—销毁"闭环:
| 端点 | 功能要点 |
|---|---|
| Real time events API | 实时事件系统的总览文档 |
| Register an event queue | 注册事件队列并返回queue_id、last_event_id,同时可拉取当前状态快照 |
| Get events from an event queue | 长轮询从队列取事件 |
| Delete an event queue | 释放队列资源 |
register 与 events:长轮询的正确打开方式
POST /register(register-queue,定义于 zulip.yaml)被官方称为"强大的端点"(powerful endpoint):它不仅注册事件队列,还能一次性返回用户当前可见的数据状态(消息、频道、用户、设置等)。其关键行为:
- 返回
queue_id与last_event_id,供后续GET /events使用; - 队列在空闲
idle_queue_timeout_secs秒后会被垃圾回收(该参数与响应字段为 Zulip 12.0 / feature level 481 新增,此前是服务端固定超时);服务端每分钟发送一次heartbeat心跳事件,帮助客户端区分"连接正常但无事件"与"连接断开"; - 若队列已被回收还去取事件,服务端返回
BAD_EVENT_QUEUE_ID错误,客户端必须捕获该错误并重新执行整个注册流程——这正是 Web 客户端在笔记本休眠后恢复时自动刷新的底层触发机制; - 原型阶段建议不带
event_types注册,先观察全部数据类型;生产环境务必设置event_types与fetch_event_types过滤器——官方直言"花几分钟做好过滤,往往能省下客户端 90% 的带宽与资源消耗"。
GET /events(get-events,定义于 zulip.yaml)负责长轮询:
queue_id:已注册队列的 ID;last_event_id:已确认收到的最高事件 ID(事件 ID 递增但不保证连续);dont_block:设为true时非阻塞返回(无事件立即返回空数组);不设置时请求会阻塞,直到有新事件或服务端发送心跳;- 客户端应使用
register响应中的event_queue_longpoll_timeout_seconds作为本端点的 HTTP 超时时间,官方保证该值高于心跳超时——直接照此实现就不会因为心跳超时增加而"提前断开"。
开发者若想深入了解队列系统的实现原理(如何避免竞态、事件分发的内部结构),可阅读 events-system.md,该文档专门讲解 Zulip 事件系统的设计细节。
Interactive bots、视频集成与移动推送
Interactive bots(交互式机器人存储)——为机器人提供简单的键值存储:
| 端点 | 功能要点 |
|---|---|
| Get / Update / Remove a bot's stored data | 按bot_user_id读取、写入、删除机器人的键值数据 |
Video call integrations(视频通话集成)——四个"创建视频会议"端点,分别对接 BigBlueButton、Constructor Groups、Nextcloud Talk、Webex:
| 端点 | 功能要点 |
|---|---|
| Create BigBlueButton / Constructor Groups / Nextcloud Talk / Webex video call | 按集成类型生成对应的视频会议会话 |
Mobile push notifications(移动推送)——约 11 个端点,覆盖设备注册与推送通道管理:
| 端点 | 功能要点 |
|---|---|
| Register a logged-in device | 注册当前登录设备(关联用户) |
| Remove a registered device | 注销设备 |
| Register E2EE push device / to bouncer | 端到端加密推送设备的注册(后者面向 Zulip 推送代理 bouncer) |
| Send an E2EE test notification / Send a test notification | 向设备发送测试推送 |
| Add / Remove an APNs device token | Apple 推送通道(APNs)令牌管理 |
| Add / Remove an FCM registration token | Google/Android 推送通道(FCM)令牌管理 |
完整的移动推送协议细节见 mobile-notifications.md。注意"E2EE 推送设备"与"普通推送设备"是两套独立端点——Zulip 移动端对通知内容做了端到端加密的选配方案。
Specialty endpoints:特殊端点
| 端点 | 功能要点 |
|---|---|
| Fetch an API key (production) | 生产环境用密码/邮箱换取 API key |
| Fetch an API key (development only) | 仅开发环境可用:免密码取 key |
| Fetch an API key (JWT) | 通过 JWT 认证换取 API key |
| List users (development only) | 仅开发环境:列出可登录用户 |
| Outgoing webhook payloads | 出站 Webhook 的负载格式规范 |
前三者是 API key 的"引导式获取"路径(适用于交互式脚本),JWT 变体则服务于第三方 SSO 集成;dev-前缀端点仅在开发模式下注册,体现了 Zulip 对"开发调试便利性"与"生产安全"的刻意区分。出站 Webhook 负载文档则定义了 Zulip 机器人把事件转发给外部服务时的 JSON 契约。
每个端点页长什么样:模板与生成机制
理解索引文档之后,还需要知道"点进去能看到什么"。api_docs/include/rest-endpoints.md中每个链接指向的独立端点页,大多由 api-doc-template.md 统一生成,其结构是:
- Usage examples:
{generate_code_example(python|javascript|curl)}三标签页(Python、JavaScript、cURL)的真实调用示例; - Parameters:
{generate_api_arguments_table|zulip.yaml|API_ENDPOINT_NAME}从 OpenAPI 定义自动生成参数表格,配{generate_parameter_description}生成参数详解; - Response:
{generate_return_values_table}自动生成的返回值说明,以及{generate_code_example|fixture}注入的示例响应(fixture)。
也就是说:索引文档(本文件)决定"有哪些端点",zulip.yaml 决定"每个端点的参数与响应",模板把它们拼装成完整页面。tools/下的检查脚本会校验索引、OpenAPI 与端点页三者的一致性,保证导航不出现 404。
维护者视角:如何把一个新端点登记进索引
对于想为 Zulip 贡献 API 端点的开发者,docs/documentation/api.md 记录了完整的文档化流程,其中与本索引直接相关的一步是:
- 在
zerver/openapi/zulip.yaml中定义端点的 OpenAPI 描述(包含operationId、summary、参数与响应 schema); - 确认端点页是否沿用 api-doc-template.md 公共模板,仅在有充分理由时才为其单独编写 Markdown;
- 在
api_docs/include/rest-endpoints.md的对应分类下新增一行:URL 必须等于operationId,链接文本必须等于 OpenAPIsummary; - 通过
http://localhost:9991/api/(本地文档服务)验证示例可复制、可运行; - 运行
./tools/create-api-changelog生成变更记录文件,并在 OpenAPI 描述中按 feature level 规范添加**Changes**标注。
这套"索引 + OpenAPI + 模板 + changelog"的规范闭环,保证了数百个端点的文档在任何版本迭代下都能保持结构一致、信息准确。
从索引到实践:建议的阅读与调用路线
- 认证先行:任何 API 调用前先阅读 api-keys.md 获取 API key、http-headers.md 了解 Basic Auth 头部格式、rest-error-handling.md 了解标准错误结构(
result/msg/code); - 选语言:官方提供 Python / JavaScript 绑定 与 其他语言客户端;官方 Python 绑定中的
client.call_endpoint甚至可以调用未收录在文档中的端点; - 发消息:从 send-message.md 入手,理解
type/to/topic/content最小调用; - 拉消息:掌握 construct-narrow.md 的 narrow 语法与
GET /messages的 anchor 窗口模型; - 做实时应用:完整走一遍
register → events(长轮询)→ delete-queue闭环,注意BAD_EVENT_QUEUE_ID的重建逻辑; - 实现集成:机器人存储、出站 Webhook(outgoing-webhook-payload.md)、定时消息(create-scheduled-message.md)、频道创建(create-stream.md)分别覆盖了自动化通知、审批流、定时任务与频道供给四大常见集成场景。
由于 Zulip 是开源项目,当文档无法回答某个问题时,你还可以直接阅读zerver/views/下的视图实现(消息相关集中在message_fetch.py、message_send.py、message_edit.py)与zerver/openapi/zulip.yaml中该端点的**Changes**标注,二者是比任何二手教程都权威的行为契约。
【免费下载链接】zulipZulip server and web application. Open-source team chat that helps teams stay productive and focused.项目地址: https://gitcode.com/GitHub_Trending/zu/zulip
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考