Rocket.Chat REST API 使用详解

系统讲解 Rocket.Chat 8.9.0 REST API 的使用方法,覆盖认证与首次调用、channels/users/settings/chat 四域端点实测闭环、分页过滤排序通用约定与 restricted-workspace 受限端点完整排障实录,已在 Ubuntu 22.04.4 实测验证。

Rocket.Chat即时通信Rocket.Chat2026/10/21

Rocket.Chat REST API 使用详解

目标:本文系统讲解 Rocket.Chat 8.9.0 工作区 REST API 的使用方法——认证与首次调用、channels/users/settings/chat 四个核心域的端点实测(请求 → 实测响应回显 → 错误码)、分页/过滤/排序通用约定,以及 restricted-workspace 受限端点的完整排障实录,全部请求与回显已在 Ubuntu 22.04.4 LTS 的 Rocket.Chat 8.9.0 实测环境验证通过。

一、环境信息

本文所有实测均在以下环境完成,命令可直接复现:

  • 操作系统:Ubuntu 22.04.4 LTS,x86_64
  • Rocket.Chat:8.9.0(服务地址 http://192.168.146.128:8133,ROOT_URL 同)
  • MongoDB:8.0.34(副本集 rs0,本机 27017)
  • 管理员账号:admin / q1w2e3r4(演示口令,生产必须换强密码)
  • 管理员已启用 TOTP 两步验证(TOTP 密钥 JBSWY3DPEHPK3PXP,演示密钥——真实环境务必保密;启用流程见 《Rocket.Chat 8.9 配置参数详解》5.3)
  • 普通测试账号:testuser(管理员经 API 创建,见 5.2)
  • 客户端工具:curl 7.81.0(HTTP 状态码经 -w '%{http_code}' 采集)、Python 3(仅 TOTP 码生成演示)
  • 部署方式:见 《Docker Compose 部署 Rocket.Chat 指南》第四章;工作区配置层操作见 《Rocket.Chat 8.9 配置参数详解》,本文聚焦 API 调用层

二、前置条件

动手调 API 前,确认以下三件事:

  1. 服务可达且版本明确。版本信息端点在 /api/info(注意:不带 /api/v1 前缀,误加前缀会得到 404):
curl -s http://192.168.146.128:8133/api/info | python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps({k:d[k] for k in ('workspaceUrl','version','minimumClientVersions','success')}, indent=2))"

实测输出(节选——原响应含一个数 KB 的 supportedVersions 签名令牌,已省略):

{
  "workspaceUrl": "192.168.146.128:8133",
  "version": "8.9",
  "minimumClientVersions": {
    "desktop": "3.9.6",
    "mobile": "4.39.0"
  },
  "success": true
}

version 字段即工作区主版本,REST 端点全部挂在 /api/v1/ 路径下。

  1. 管理员账号可登录且已配置 TOTP。Rocket.Chat 8.x 对登录与敏感操作强制两步验证,未配置 TOTP 时连登录都会被拒(实测见 4.2)。TOTP 启用全链见 《Rocket.Chat 8.9 配置参数详解》5.3。

  2. curl 可用。本文全部示例使用 curl,HTTP 状态码统一用 -w '%{http_code}' 采集——Rocket.Chat 的业务错误统一返回 200~400 区间的 HTTP 状态 + JSON 错误体,只看状态码会漏掉 success:false 的业务失败,必须核对响应体。

三、API 总览

维度说明
协议与风格HTTP REST,请求/响应均为 JSON(Content-Type: application/json)
版本与基址URL 路径版本化,当前主版本 /api/v1;版本元信息在 /api/info
认证方式登录换取 X-Auth-Token + X-User-Id 双头(本文实测主线);官方文档另列 Personal Access Token 方式,本版实测其创建端点不可用(见 5.4)
敏感操作登录、用户管理、设置修改等一律要求两步验证头:X-2FA-Code + X-2FA-Method: totp
限流约定两层:全局桶默认 600 次/分钟(源码为 Limit_Calls_Default × 60),端点级按端点各自配置(兜底值为设置项 API_Enable_Rate_Limiter_Limit_Calls_Default,本工作区 10 次/60000ms,实测见 7.5)
错误响应统一 {"success":false,"error":"<信息>","errorType":"<错误码>"} 结构,HTTP 状态多为 400/401

本文实测覆盖的端点域:

域端点前缀典型用途本文实测小节
频道/api/v1/channels.*频道创建/查询/成员/历史5.1
用户/api/v1/users.*用户创建/查询/更新5.2
设置/api/v1/settings*工作区参数读写5.3
消息/api/v1/chat.*发消息(本环境受限,排障实录)5.4
私聊/api/v1/im.*直消息会话(部分端点本版不可用)5.4

四、认证与首次调用

4.1 无认证调用的第一反应

不带任何认证头调用受保护端点:

curl -s -w '\nHTTP %{http_code}\n' http://192.168.146.128:8133/api/v1/me

实测输出:

{"success":false,"error":"You must be logged in to do this.","status":"error","message":"You must be logged in to do this."}
HTTP 401

HTTP 401 + 统一错误体,这是后续所有认证问题的基线对照。

4.2 登录第一步:不带 2FA 头会被拒

管理员已启用 TOTP 后,登录必须携带两步验证头。先看不带头的实际反应:

curl -s -w '\nHTTP %{http_code}\n' -X POST http://192.168.146.128:8133/api/v1/login \
  -H 'Content-Type: application/json' \
  -d '{"user":"admin","password":"q1w2e3r4"}'

实测输出:

{"success":false,"error":"totp-required","status":"error","details":{"method":"totp","codeGenerated":false,"availableMethods":["totp"]},"message":"TOTP Required"}
HTTP 401

details.availableMethods: ["totp"] 明确告诉调用方可用的二次验证方式是 TOTP——这个字段是排错时判断「该带什么头」的直接依据。

4.3 生成当前 TOTP 码

TOTP 基于 RFC 6238(30 秒窗口、6 位数字、SHA-1),与 Google Authenticator 等标准验证器一致。命令行生成当前码:

python3 -c "import hmac,hashlib,base64,struct,time; key=base64.b32decode('JBSWY3DPEHPK3PXP'); t=struct.pack('>Q', int(time.time())//30); h=hmac.new(key,t,hashlib.sha1).digest(); o=h[-1]&0x0f; print('%06d' % ((struct.unpack('>I',h[o:o+4])[0]&0x7fffffff)%1000000))"

实测输出(30 秒有效窗口内,读者执行时数值不同属正常):

602220

4.4 登录成功:双头令牌

携带 X-2FA-Code 与 X-2FA-Method 重新登录:

curl -s -X POST http://192.168.146.128:8133/api/v1/login \
  -H 'Content-Type: application/json' \
  -H "X-2FA-Code: 602220" -H "X-2FA-Method: totp" \
  -d '{"user":"admin","password":"q1w2e3r4"}'

实测输出(节选——me 字段含完整用户偏好设置,已折叠):

{"status":"success","data":{"userId":"FAqZDu2LStf9g6nku","authToken":"fTKzEOcCdgz1U0FlndgyFDKqM3h1QYdZPqoeRPzFHTT","me":{"_id":"FAqZDu2LStf9g6nku","services":{"totp":{"enabled":true},"password":{"exists":true}},"emails":[{"address":"admin@example.com","verified":false}],"name":"Administrator","roles":["user","admin"],"status":"offline","active":true,"username":"admin",…}},"success":true}

关键字段:userId + authToken 就是后续请求的认证双头值;roles 可确认账号权限(admin)。

后续请求统一封装为两个头(下文用 $TOKEN/$USERID 指代):

X-Auth-Token: fTKzEOcCdgz1U0FlndgyFDKqM3h1QYdZPqoeRPzFHTT
X-User-Id: FAqZDu2LStf9g6nku

4.5 首个认证请求:/me

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" http://192.168.146.128:8133/api/v1/me

实测输出(节选):

{"_id":"FAqZDu2LStf9g6nku","services":{"totp":{"enabled":true},"password":{"exists":true}},"emails":[{"address":"admin@example.com","verified":false}],"name":"Administrator","roles":["user","admin"],"status":"offline","active":true,"username":"admin","…,"success":true}

/me 返回当前账号完整资料,适合做脚本里的「令牌自检」。

4.6 错误 TOTP 码的反应

验证码填错(如窗口切换后旧码):

curl -s -w '\nHTTP %{http_code}\n' -X POST http://192.168.146.128:8133/api/v1/login \
  -H 'Content-Type: application/json' \
  -H "X-2FA-Code: 000000" -H "X-2FA-Method: totp" \
  -d '{"user":"admin","password":"q1w2e3r4"}'

实测输出:

{"success":false,"error":"totp-invalid","status":"error","details":{"method":"totp","codeGenerated":false,"availableMethods":["totp"]},"message":"TOTP Invalid"}
HTTP 401

totp-required(没带验证码)与 totp-invalid(带了但不对) 是两个不同错误,排错时先分清。

五、各 API 域详解

本章按域给出「端点 → 方法 → 参数 → 请求示例 → 实测响应 → 错误码」完整闭环。认证双头统一记为 $TOKEN/$USERID,敏感操作另带 2FA 双头。

5.1 channels 域:频道管理

channels.create — 创建频道

POST /api/v1/channels.create,body 参数 name(公开频道名,小写字母数字与连字符):

curl -s -X POST http://192.168.146.128:8133/api/v1/channels.create \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H 'Content-Type: application/json' \
  -d '{"name":"api-demo"}'

实测输出:

{"channel":{"_id":"6ad89d77115bffdf768a386b","fname":"api-demo","_updatedAt":"2026-10-21T11:09:43.486Z","name":"api-demo","t":"c","msgs":0,"usersCount":1,"u":{"_id":"FAqZDu2LStf9g6nku","username":"admin","name":"Administrator"},"ts":"2026-10-21T11:09:43.473Z","ro":false,"default":false,"sysMes":true},"success":true}

_id(6ad89d77115bffdf768a386b)是后续所有频道操作的 roomId;t:"c" 表示公开频道。

channels.info — 频道详情

GET /api/v1/channels.info,参数 roomId 或 roomName 二选一。两个参数形态都实测:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  "http://192.168.146.128:8133/api/v1/channels.info?roomId=GENERAL"

实测输出:

{"channel":{"_id":"GENERAL","ts":"2026-10-21T07:27:59.891Z","t":"c","name":"general","usernames":[],"msgs":2,"usersCount":2,"_updatedAt":"2026-10-21T11:09:43.702Z","u":{"_id":"rocket.cat","username":"rocket.cat","name":"Rocket.Cat"},"default":true},"success":true}
curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  "http://192.168.146.128:8133/api/v1/channels.info?roomName=general"

实测输出(与 roomId 调用一致,success:true):

{"channel":{"_id":"GENERAL",…},"success":true}

内置默认频道 _id 固定为字符串 GENERAL(业务自建频道是 24 位十六进制串)。

参数传错(不存在的频道):

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  "http://192.168.146.128:8133/api/v1/channels.info?roomId=does-not-exist"

实测输出:

{"success":false,"error":"The required \"roomId\" or \"roomName\" param provided does not match any channel [error-room-not-found]","errorType":"error-room-not-found"}

参数名写错(本端点不接受 channel 参数,只认 roomId/roomName):

{"success":false,"errorType":"error-invalid-params","error":"must have required property 'roomId'\n must have required property 'roomName'\n must match a schema in anyOf"}

channels.list — 频道列表与分页排序

GET /api/v1/channels.list,支持 count/offset 分页与 sort 排序(通用约定详见第六章)。按名称升序列出全部频道:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  'http://192.168.146.128:8133/api/v1/channels.list?count=10&sort=%7B%22name%22%3A1%7D'

实测输出(sort 参数是 URL 编码后的 {"name":1},返回按 name 升序:api-demo → general → ops-notify):

{"channels":[{"_id":"6ad89d77115bffdf768a386b","fname":"api-demo",…,"name":"api-demo",…},{"_id":"GENERAL",…,"name":"general",…},{"_id":"6ad86aa055a07eed2cb9ca5f","fname":"ops-notify",…,"name":"ops-notify",…}],"count":3,"offset":0,"total":3,"success":true}

channels.history — 消息历史

GET /api/v1/channels.history,参数 roomId(必填)、count:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  "http://192.168.146.128:8133/api/v1/channels.history?roomId=GENERAL&count=5"

实测输出(general 频道目前只有两条系统消息——t:"uj" 是用户加入频道的系统事件):

{"messages":[{"_id":"6ad89d77115bffdf768a386e","t":"uj","rid":"GENERAL","ts":"2026-10-21T11:09:43.702Z","msg":"testuser","u":{"_id":"Fwt9G5yomjcxtGJ9W","username":"testuser","name":"Test User"},"groupable":false,"_updatedAt":"2026-10-21T11:09:43.702Z"},{"_id":"6ad86a5955a07eed2cb9ca5b","t":"uj","rid":"GENERAL","ts":"2026-10-21T07:31:37.728Z","msg":"rcadmin","u":{"_id":"FAqZDu2LStf9g6nku","username":"rcadmin","name":"Administrator"},"groupable":false,"_updatedAt":"2026-10-21T07:31:37.728Z"}],"success":true}

roomId 缺失时的报错(参数校验先于业务执行):

{"success":false,"errorType":"error-invalid-params","error":"must NOT have fewer than 1 characters\n must have required property 'roomName'\n must match exactly one schema in oneOf"}

channels.members — 成员列表

GET /api/v1/channels.members,参数 roomId:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  "http://192.168.146.128:8133/api/v1/channels.members?roomId=GENERAL"

实测输出:

{"members":[{"_id":"FAqZDu2LStf9g6nku","name":"Administrator","status":"offline","_updatedAt":"2026-10-21T11:11:00.173Z","username":"admin"},{"_id":"Fwt9G5yomjcxtGJ9W","username":"testuser","name":"Test User","status":"offline","_updatedAt":"2026-10-21T11:11:00.283Z"}],"count":2,"offset":0,"total":2,"success":true}

channels.invite — 拉用户入频道

POST /api/v1/channels.invite,body 参数 roomId + userId(把 5.2 创建的 testuser 拉进 api-demo):

curl -s -X POST http://192.168.146.128:8133/api/v1/channels.invite \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H 'Content-Type: application/json' \
  -d '{"roomId":"6ad89d77115bffdf768a386b","userId":"Fwt9G5yomjcxtGJ9W"}'

实测输出(usersCount 从 1 变 2,msgs 加了一条邀请系统消息):

{"channel":{"_id":"6ad89d77115bffdf768a386b","fname":"api-demo","_updatedAt":"2026-10-21T11:11:00.284Z","name":"api-demo","t":"c","msgs":1,"usersCount":2,"u":{"_id":"FAqZDu2LStf9g6nku","username":"admin","name":"Administrator"},"ts":"2026-10-21T11:09:43.473Z","ro":false,"default":false,"sysMes":true},"success":true}

💡 技术拓展:channels.* 与 groups.*、im.* 是三套平行走廊——公开频道走 channels.*、私有群组走 groups.*、直消息走 im.*,端点形态几乎镜像(channels.create 对应 groups.create/im.create,以此类推)。掌握了 channels.* 一套,另外两套换前缀即可;区别在于权限语义(私有群组要求成员身份才能查询)。

5.2 users 域:用户管理

users.create — 创建用户

POST /api/v1/users.create,body 参数 name/email/password/username。管理类端点要求 2FA 头:

curl -s -X POST http://192.168.146.128:8133/api/v1/users.create \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H "X-2FA-Code: $TOTP" -H "X-2FA-Method: totp" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Test User","email":"testuser@example.com","password":"q1w2e3r4","username":"testuser"}'

实测输出:

{"user":{"_id":"Fwt9G5yomjcxtGJ9W","createdAt":"2026-10-21T11:09:43.689Z","username":"testuser","emails":[{"address":"testuser@example.com","verified":false}],"name":"Test User","type":"user","roles":["user"],"status":"offline","active":true,"_updatedAt":"2026-10-21T11:09:43.709Z","__rooms":["GENERAL"],"settings":{}},"success":true}

_id(Fwt9G5yomjcxtGJ9W)是后续用户操作的 userId;roles:["user"] 默认普通角色。

新用户登录不需要 TOTP(两步验证按账号维度启用,testuser 未配置):

curl -s -X POST http://192.168.146.128:8133/api/v1/login \
  -H 'Content-Type: application/json' \
  -d '{"user":"testuser","password":"q1w2e3r4"}'

实测输出(节选):

{"status":"success","data":{"userId":"Fwt9G5yomjcxtGJ9W","authToken":"DPmdPj3HZFAS640_g9loBX6G7YjRHd2Tunld2jtnTRl","me":{"_id":"Fwt9G5yomjcxtGJ9W","services":{"email2fa":{"enabled":true},"password":{"exists":true}},"username":"testuser",…}},"success":true}

注意 services.email2fa.enabled:true——工作区设置 Accounts_TwoFactorAuthentication_By_Email_Auto_Opt_In 默认开启(见 《Rocket.Chat 8.9 配置参数详解》5.3),新用户自动登记 Email 2FA 方式,但只在敏感操作时才要求验证码,普通登录与读操作不受影响。

users.info — 用户详情

GET /api/v1/users.info,参数 userId 或 username:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  "http://192.168.146.128:8133/api/v1/users.info?username=testuser"

实测输出:

{"user":{"_id":"Fwt9G5yomjcxtGJ9W","createdAt":"2026-10-21T11:09:43.689Z","username":"testuser","emails":[{"address":"testuser@example.com","verified":false}],"name":"Test User","type":"user","roles":["user"],"status":"offline","active":true,"canViewAllInfo":true},"success":true}

users.list — 用户列表与字段过滤

GET /api/v1/users.list,支持 count/offset/fields 投影:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  'http://192.168.146.128:8133/api/v1/users.list?count=5&fields=%7B%22name%22%3A1%2C%22username%22%3A1%2C%22active%22%3A1%7D'

实测输出(fields 参数是 URL 编码后的 {"name":1,"username":1,"active":1},投影生效——回显只含指定字段加固定主键):

{"users":[{"_id":"FAqZDu2LStf9g6nku","emails":[{"address":"admin@example.com","verified":false}],"name":"Administrator","type":"user","roles":["user","admin"],"status":"offline","active":true,"username":"admin","lastLogin":"2026-10-21T11:09:43.239Z","nameInsensitive":"administrator"},{"_id":"rocket.cat","name":"Rocket.Cat","username":"rocket.cat","status":"online","active":true,"type":"bot","roles":["bot"],"avatarETag":"NbuzBeDA2ZvsPpiTJ","nameInsensitive":"rocket.cat"},{"_id":"Fwt9G5yomjcxtGJ9W","username":"testuser","emails":[{"address":"testuser@example.com","verified":false}],"name":"Test User","type":"user","roles":["user"],"status":"offline","active":true,"nameInsensitive":"test user"}],"count":3,"offset":0,"total":3,"success":true}

列表里出现的 rocket.cat 是内置系统机器人账号(type:"bot")。

users.update — 更新用户

POST /api/v1/users.update,body 参数 userId + data 对象(带 2FA 头):

curl -s -X POST http://192.168.146.128:8133/api/v1/users.update \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H "X-2FA-Code: $TOTP" -H "X-2FA-Method: totp" \
  -H 'Content-Type: application/json' \
  -d '{"userId":"Fwt9G5yomjcxtGJ9W","data":{"name":"Test User (via API)"}}'

实测输出(name 已变更;__rooms 显示该用户所在频道):

{"user":{"_id":"Fwt9G5yomjcxtGJ9W","createdAt":"2026-10-21T11:09:43.689Z","username":"testuser","emails":[{"address":"testuser@example.com","verified":false}],"name":"Test User (via API)","type":"user","roles":["user"],"status":"offline","active":true,"_updatedAt":"2026-10-21T11:12:37.051Z","__rooms":["GENERAL","6ad89d77115bffdf768a386b"],"settings":{},"lastLogin":"2026-10-21T11:10:03.830Z"},"success":true}

5.3 settings 域:工作区设置读写

settings 域与工作区参数体系是一体两面——API 层的全部实测闭环(含 2FA 要求、三条修改通道对比、889 项参数总览)在 《Rocket.Chat 8.9 配置参数详解》第三章有完整展开,本节只给最小可用对。

读单个参数:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  http://192.168.146.128:8133/api/v1/settings/Site_Name

实测输出:

{"_id":"Site_Name","value":"Rocket.Chat","success":true}

写单个参数(敏感操作,必须带 2FA 头):

curl -s -X POST http://192.168.146.128:8133/api/v1/settings/Site_Name \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H "X-2FA-Code: $TOTP" -H "X-2FA-Method: totp" \
  -H 'Content-Type: application/json' \
  -d '{"value":"RC 运维实验室"}'

实测输出:

{"success": true}

全量参数清单(count=0 不分页,配合 fields 投影只取键名):

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  'http://192.168.146.128:8133/api/v1/settings?count=0&fields={"_id":1}' \
  | python3 -c "import sys,json; d=json.load(sys.stdin); print('total:', d['total'])"

实测输出:

total: 889

5.4 chat 域与受限端点:restricted-workspace 排障实录

chat 域是 REST API 最核心的写通道(chat.postMessage 发消息、chat.sendMessage 带预生成消息 ID 发送),也是本环境实测遇到的最大坑——两个端点一律返回 restricted-workspace。本节完整记录复现、定位、根因与边界。

复现:管理账号发消息被拒

curl -s -w '\nHTTP %{http_code}\n' -X POST http://192.168.146.128:8133/api/v1/chat.postMessage \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H 'Content-Type: application/json' \
  -d '{"channel":"general","text":"hello from REST API"}'

实测输出:

{"success":false,"error":"restricted-workspace"}
HTTP 400
curl -s -X POST http://192.168.146.128:8133/api/v1/chat.sendMessage \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H 'Content-Type: application/json' \
  -d '{"message":{"rid":"GENERAL","msg":"hello via sendMessage"}}'

实测输出:

{"success":false,"error":"restricted-workspace"}

排除账号因素:普通用户同样被拒

用 5.2 创建的 testuser 登录后调用同一端点:

curl -s -X POST http://192.168.146.128:8133/api/v1/chat.postMessage \
  -H "X-Auth-Token: $TTOKEN" -H "X-User-Id: $TUSERID" \
  -H 'Content-Type: application/json' \
  -d '{"channel":"api-demo","text":"hello from testuser"}'

实测输出:

{"success":false,"error":"restricted-workspace"}

管理员与普通用户都被拒,说明限制在工作区层面而非账号权限层面。

排除参数因素:空 body 的报错不同

curl -s -w '\nHTTP %{http_code}\n' -X POST http://192.168.146.128:8133/api/v1/chat.postMessage \
  -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  -H 'Content-Type: application/json' \
  -d '{}'

实测输出:

{"success":false,"errorType":"invalid-params","error":"must have required property 'roomId'\n must have required property 'channel'\n must match exactly one schema in oneOf"}
HTTP 400

参数校验错误是 invalid-params 而不是 restricted-workspace——说明请求已通过参数校验、在业务执行层被拒,且参数校验发生在限制检查之前。

定位:限制剩余天数设置项

工作区设置里有一个直接对应的键(读设置不需要 2FA,写才需要):

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  http://192.168.146.128:8133/api/v1/settings/Cloud_Workspace_AirGapped_Restrictions_Remaining_Days

实测输出:

{"_id":"Cloud_Workspace_AirGapped_Restrictions_Remaining_Days","value":0,"success":true}

value: 0——限制宽限期已耗尽。Rocket.Chat 社区版工作区需要定期向 Rocket.Chat Cloud 上报使用统计(或注册云工作区),空气隔离/无法外联的网络里上报持续失败,宽限期归零后许可证模块(AirGappedRestriction)对受保护端点一律抛 restricted-workspace。本环境日志里可见对外连接 ETIMEDOUT(内网无外联),与该判定吻合。

边界:受限域清单与不受限域

实测受限与可用的端点边界:

端点实测结果说明
POST /chat.postMessagerestricted-workspace受限
POST /chat.sendMessagerestricted-workspace受限
POST /im.postMessage404 Not Found本版该 REST 端点不存在(非受限问题)
POST /users.createPersonalAccessToken404 Not Found本版该 REST 端点不存在(非受限问题)
GET /channels.*(info/list/history/members)正常读通道不受限
POST /channels.create / channels.invite正常频道管理不受限
POST /users.create / users.update(带 2FA)正常用户管理不受限
GET/POST /settings*(写带 2FA)正常设置读写不受限

结论:restricted-workspace 只挡消息写入类端点;频道与用户管理、设置读写全部可用。内网/离线环境的解法只有两条——给工作区配外联通道并完成云注册,或取得有效企业许可;工作区设置 RC_DISABLE_STATISTICS_REPORTING 只是关闭统计上报,并不会解除该限制(无上报记录时判定反而更直接生效)。对本环境(内网实测)而言,消息写入经 Web 界面/DDP 通道完成,REST 层的 restricted-workspace 属预期行为。

六、分页、过滤、排序通用约定

列表类端点(channels.list、users.list、channels.history、settings 等)共享一套查询约定,全部实测验证:

分页:count(页大小)+ offset(偏移量),响应体固定返回 count/offset/total 三元组。翻页语义用实测看最清楚——总数 2 时取 offset=2:

curl -s -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  'http://192.168.146.128:8133/api/v1/channels.list?count=2&offset=2'

实测输出:

{"channels":[],"count":0,"offset":2,"total":2,"success":true}

total 是全量计数、count 是本页条数——脚本里「取完一页、total 未尽、offset += count」即可安全翻页。

排序:sort 参数是 JSON 对象(字段名 → 1 升序 / -1 降序),必须 URL 编码后拼接({"name":1} → %7B%22name%22%3A1%7D),实测回显见 5.1 channels.list(返回严格按 name 升序)。

字段过滤:fields 参数同样是 JSON 对象(字段名 → 1 只取 / 0 剔除),同样需 URL 编码,实测回显见 5.2 users.list(投影生效,未指定字段被剔除)。

两个传 JSON 的参数如果直接裸写 ?sort={"name":1},curl 会把花括号与引号原样发出,部分端点可解析但行为不可靠——规范做法是编码后传输,脚本里用 curl --get --data-urlencode 更省心:

curl -s --get -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $USERID" \
  --data-urlencode 'sort={"name":1}' --data-urlencode 'count=10' \
  http://192.168.146.128:8133/api/v1/channels.list

实测输出与 5.1 手工编码调用一致(success:true,按名称升序)。

七、常见问题(FAQ)

Q1:登录返回 totp-required 且 availableMethods 为空?

该账号没有任何可用的两步验证方式,需要先为账号启用 TOTP(界面引导录入验证器,或应急场景经数据库层写入 services.totp,全链步骤见 《Rocket.Chat 8.9 配置参数详解》5.3)。启用后 availableMethods 会变成 ["totp"],此时带 X-2FA-Code + X-2FA-Method: totp 头登录即可。

Q2:带了 2FA 头却返回 totp-invalid?

验证码不对。按出现概率排查:① 本机时间与服务器偏差超过 30 秒窗口(NTP 未同步是头号原因,用 timedatectl 核对两端时间);② 密钥录错(base32 密钥核对大小写与填充);③ 拿到了上一窗口的旧码(生成后 30 秒内必须用掉,脚本里应即算即用)。

Q3:chat.postMessage/chat.sendMessage 返回 restricted-workspace?

工作区未连接 Rocket.Chat Cloud 且统计上报持续失败,空气隔离限制(AirGappedRestriction)宽限期耗尽(Cloud_Workspace_AirGapped_Restrictions_Remaining_Days 归 0)后的预期行为,完整排障链与受限域边界清单见 5.4。与账号权限、参数写法无关——管理员与普通用户、正确与错误参数的报错路径都不同,可据此自证。

Q4:官方文档里的端点(如 im.postMessage、users.createPersonalAccessToken)实测 404?

REST 端点随版本演进有增删,8.9.0 实测这两个端点不存在(5.4 边界清单)。核对方法:先 GET /api/info 确认工作区版本,再对照 developer.rocket.chat 的 REST API 文档切换到对应版本阅读;同域替代端点优先在同前缀族内找(如 im.* 下找直消息相关端点)。

Q5:什么时候会遇到 429?实测怎么打都打不出来。

本环境实测:channels.history 连发 12 次、users.info 连发 30 次全部 HTTP 200(5.4/7.5 实测记录),未触发限流。原因是限流分两层——全局桶默认 600 次/分钟(源码实现为 API_Enable_Rate_Limiter_Limit_Calls_Default × 60),端点级限额按端点各自配置,设置项里的 10 次/60000ms 是未单独配置端点的兜底值,常用读端点的实际额度高于兜底。429 一般出现在高频写操作或未配额端点上;真触发时按 《Rocket.Chat 8.9 配置参数详解》5.6 调整 API_Enable_Rate_Limiter_Limit_Calls_Default 或让调用方退避。

Q6:sort/fields 参数传 JSON 报参数错误?

这两个参数的值是 JSON 对象,必须 URL 编码({"name":1} → %7B%22name%22%3A1%7D),或改用 curl --data-urlencode 自动编码(第六章有对比实测)。裸写花括号在部分端点能碰巧工作,但不可靠。

八、参考链接

  1. REST API 总览(端点族与认证):https://developer.rocket.chat/reference/api/rest-api
  2. Authentication 端点(login/logout/me):https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/authentication-endpoints
  3. Channels 端点族:https://developer.rocket.chat/reference/api/rest-api/endpoints/room-endpoints/channels-endpoints
  4. Users 端点族:https://developer.rocket.chat/reference/api/rest-api/endpoints/user-endpoints
  5. Chat 端点族(postMessage/sendMessage):https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/chat-endpoints
  6. Settings 端点:https://developer.rocket.chat/reference/api/rest-api/endpoints/core-endpoints/settings-endpoints
  7. Rate Limiter 说明:https://developer.rocket.chat/reference/api/rest-api/rate-limiter
  8. 两步验证官方指南:https://docs.rocket.chat/docs/two-factor-authentication
  9. 本文部署载体:《Docker Compose 部署 Rocket.Chat 指南》;参数体系:《Rocket.Chat 8.9 配置参数详解》