plugNmeet 2.5.3 REST API 调用指南
讲清 plugNmeet 2.5.3 管理 REST API 鉴权(API-KEY + HMAC-SHA256 双头)与调用方法:建房、签发入会 JWT、查询与结束房间全生命周期实测回显,附三类 401 错误码与排错方法。
plugNmeet 2.5.3 REST API 调用指南
目标:讲清 plugNmeet 2.5.3 管理 REST API 的鉴权机制(API-KEY + HMAC-SHA256 双头)与调用方法,实测建房、签发入会 JWT、查询房间、结束会议的完整生命周期,并给出三类鉴权失败的真实回显与排错方法。
一、环境信息
- plugNmeet 服务端 v2.5.3(官方镜像部署,Web/API 端口 8145)
- 调用端:Python 3.14 标准库(
urllib.request,无需第三方依赖) - 凭证:
API-KEY: APIkey1234567、SECRET: q1w2e3r4plugnmeetsecret0123456789abcd(取自config.yaml的client.api_key/client.secret) - 实测时间:2026-10-26
🔗 服务部署与配置项出处见 《plugNmeet 2.5.3 Docker Compose 部署指南》、《plugNmeet 2.5.3 配置参数详解》;组件背景见 《plugNmeet 2.5.3 介绍与选型指南》。
二、鉴权机制
2.1 双请求头
所有 /auth/* 端点(源码路由组 auth := fiberApp.Group("/auth", ...HandleAuthHeaderCheck))要求两个自定义请求头:
| 头 | 值 | 说明 |
|---|---|---|
API-KEY | config.yaml 的 client.api_key | 明文标识,先查存在性 |
HASH-SIGNATURE | HMAC-SHA256(secret, 请求体原文) 的 hex 小写 | 对请求体整体签名 |
两个规则实测验证:
- 签名密钥是
client.secret,不是 api_key; - 签名输入是请求体的原始字节——签名用什么序列化,发送就必须原样发同一份字节。本文用 Python
json.dumps(payload, separators=(",", ":"))(紧凑无空格)先签名再发送,保持一致即通过;若签名与发送内容序列化不一致,服务端验签必失败。
2.2 可复用调用函数
import hashlib
import hmac
import json
import urllib.request
BASE = "http://127.0.0.1:8145" # 生产环境换成 https://你的域名
API_KEY = "APIkey1234567"
API_SECRET = "q1w2e3r4plugnmeetsecret0123456789abcd"
def call(path: str, payload: dict) -> dict:
body = json.dumps(payload, separators=(",", ":")) # 先定序列化
sig = hmac.new(API_SECRET.encode(), body.encode(),
hashlib.sha256).hexdigest() # 对原文签名
req = urllib.request.Request(
BASE + path,
data=body.encode(), # 原样发送
headers={
"Content-Type": "application/json",
"API-KEY": API_KEY,
"HASH-SIGNATURE": sig,
},
method="POST",
)
with urllib.request.urlopen(req, timeout=15) as resp:
return json.loads(resp.read().decode())
2.3 鉴权失败回显(实测)
服务端对三种典型错误返回不同的 status_code,排错时直接对照:
| 场景 | HTTP | 响应体 |
|---|---|---|
| 签名错误(密钥不对/签名与体不一致) | 401 | {"status":false, "msg":"Failed to verify provided authentication details.", "status_code":"INVALID_TOKEN_OR_SIGNATURE"} |
| 缺头 | 401 | {"status":false, "msg":"Missing API-KEY header.", "status_code":"MISSING_REQUIRED_PARAMETER"} |
| API-KEY 不存在 | 401 | {"status":false, "msg":"Invalid API key provided.", "status_code":"INVALID_API_KEY"} |
三、端点总览
v2.5.3 的 /auth/* 管理面(源码 router.go 实录,全部 POST):
| 组 | 端点 | 用途 |
|---|---|---|
/auth | /getClientFiles | 获取客户端静态资源路径 |
/auth/room | /create | 创建房间(含完整房间元数据) |
/getJoinToken | 为用户签发入会 JWT | |
/isRoomActive | 房间是否在会中 | |
/getActiveRoomInfo | 单房间详情(含参与者) | |
/getActiveRoomsInfo | 全部活动房间列表 | |
/endRoom | 结束房间 | |
/fetchPastRooms | 分页查历史房间 | |
/broadcastToRoom | 全房间广播自定义消息 | |
/uploadWhiteboardFile | 上传白板文件 | |
/createPoll | 创建投票 | |
/auth/recording | /fetch /info /updateMetadata /mergeRecordings /delete /getDownloadToken | 录制管理 |
/auth/analytics | /fetch /delete /getDownloadToken | 会后分析 |
/auth/artifact | /fetch /info /delete /getDownloadToken | AI 产物 |
/auth/recorder | /notify | 录制器事件上报(录制组件专用) |
另有两条平级体系:浏览器端 /api/*(入会 JWT 鉴权,会议内交互);BigBluebutton 兼容层 /{apiKey}/bigbluebutton/api/*(create/join/end 等全家桶,供已有 BBB 集成的第三方系统平迁)。
四、实战:完整生命周期实测
以下全部为对 2.5.3 实测环境真实调用的回显(响应 JSON 保留服务端原始格式,键后带空格)。
4.1 创建房间 /auth/room/create
请求体(room_id 必填;metadata.room_features 是 v2.5.3 的房间能力集):
{"room_id":"demo-room-01","metadata":{"room_title":"演示房间","welcome_message":"欢迎加入 plugNmeet 2.5.3 演示会议","room_features":{"allow_webcams":true,"mute_on_start":false,"allow_self_permission":true,"admin_only_webcams":false,"allow_view_other_webcams":true,"allow_view_other_participants":true,"allow_polls":true,"connection_quality_calculator":false,"allow_rtmp":false,"allow_recording":false,"allow_virtual_background":false,"external_media_player":false,"quiz":false,"chat_features":{"allow_chat":true,"allow_file_upload":true,"allow_chat_reactions":true},"shared_note_pad_features":{"allowed_shared_note_pad":true},"whiteboard_features":{"allowed_whiteboard":true},"speak_request_features":{"allow_speak_request":true}}}}
响应(截取,服务端会回填全部默认能力):
{"status":true, "msg":"success", "status_code":"SUCCESS", "room_info":{"room_title":"演示房间", "room_id":"demo-room-01", "sid":"e4356362-b1cf-4c49-914a-907defb450e1", "joined_participants":"0", "is_running":1, "is_recording":0, "is_active_rtmp":0, "webhook_url":"", "is_breakout_room":0, "parent_room_id":"", "creation_time":"1793010994", "metadata":"{...完整JSON字符串...}"}}
实测要点:
- 字段级校验:
metadata.room_features缺失时 2.5.3 直接拒绝并返回 protovalidate 的字段错误明细(本实验首次调用即遇到),建房请求需带完整room_features结构。 - 请求字段与响应字段并非一一映射:实测请求里发
chat_features.allow_chat:true,服务端回显是"chat_features":{"is_allow":false, "is_allow_file_upload":false, "allowed_file_types":[]}——能力集内部是「is_allow允许 /is_active激活」两级开关模型,且部分请求字段名与响应字段名不同。以服务端回显为准核对能力状态,不要假设请求字段会原样落回。 sid是房间在 LiveKit 侧的会话 ID;creation_time为 Unix 秒。
4.2 签发入会 Token /auth/room/getJoinToken
请求体:
{"room_id":"demo-room-01","user_info":{"name":"admin","user_id":"user-admin-001","is_admin":true,"hidden":false}}
响应(token 为标准 JWT):
{"status":true, "msg":"success", "status_code":"SUCCESS", "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3OTMwMTMzMjQsImlzX2FkbWluIjp0cnVlLCJpc3MiOiJBUElrZXkxMjM0NTY3IiwibmFtZSI6ImFkbWluIiwibmJmIjoxNzkzMDEyNzI0LCJyb29tX2lkIjoiZGVtby1yb29tLTAxIiwic3ViIjoidXNlci1hZG1pbi0wMDEiLCJ1c2VyX2lkIjoidXNlci1hZG1pbi0wMDEifQ.09AvIsKccoQkQqRsVsdu5jTPW9lL5advxAJ9pFRwGsA"}
解码后的 JWT 结构(实测):
// header
{"alg": "HS256", "typ": "JWT"}
// payload
{"exp": 1793013324, "is_admin": true, "iss": "APIkey1234567", "name": "admin", "nbf": 1793012724, "room_id": "demo-room-01", "sub": "user-admin-001", "user_id": "user-admin-001"}
iss即client.api_key;exp-nbf = 600秒,对应config.yaml的token_validity: 10m(客户端会自动续期)。- 签名密钥是
client.secret(与 API 鉴权同一把),拿到 token 即可入会,务必走 HTTPS 下发。 - 入会 URL:
https://<域名>/?access_token=<token>。
4.3 查询房间
单房间(含 participants_info 实时成员列表):
// POST /auth/room/getActiveRoomInfo {"room_id":"demo-room-01"}
{"status":true, "msg":"success", "status_code":"SUCCESS", "room":{"room_info":{...}, "participants_info":[]}}
活动房间列表:
// POST /auth/room/getActiveRoomsInfo {}
{"status":true, "msg":"success", "status_code":"SUCCESS", "rooms":[{"room_info":{...}, "participants_info":[]}]}
注意空态语义(实测):无活动房间时返回 {"status":false, "msg":"no active room found", "status_code":"NOT_FOUND", "rooms":[]}——HTTP 仍是 200,rooms 为空数组且 status:false,业务代码要按 rooms 数组判空而不是 status 布尔。
4.4 房间在会判定与结束(闭环实测)
// POST /auth/room/isRoomActive {"room_id":"demo-room-01"}
{"status":true, "msg":"room is active", "status_code":"SUCCESS", "is_active":true}
// POST /auth/room/endRoom {"room_id":"demo-room-01"}
{"status":true, "msg":"success", "status_code":"SUCCESS"}
实测发现 endRoom 是异步关闭:返回 success 后立刻再查 isRoomActive 仍可能拿到 is_active:true(房间状态清理经 NATS 广播、依赖组件逐个退出),本次实测约 6 秒后状态才落定:
// 数秒后再查
{"status":true, "msg":"room not found", "status_code":"ROOM_NOT_FOUND", "is_active":false}
{"status":false, "msg":"no active room found", "status_code":"NOT_FOUND", "rooms":[]}
集成方注意:结束房间后不要立即同步查询并断言,应轮询直到 is_active:false/ROOM_NOT_FOUND;关闭过渡期对同一房间重复 endRoom 还可能等到请求超时(实测现象),属正常竞态。
五、错误码速查(/auth 面)
| status_code | 含义 | 处置 |
|---|---|---|
SUCCESS | 成功 | — |
INVALID_TOKEN_OR_SIGNATURE | 验签失败 | 核对 secret 与签名输入=请求体原文 |
MISSING_REQUIRED_PARAMETER | 缺 API-KEY 头 | 补双头 |
INVALID_API_KEY | key 不存在 | 核对 api_key |
NOT_FOUND | 资源不存在(含空列表) | 判空处理 |
ROOM_NOT_FOUND | 房间不存在/已结束 | 先 create 再操作 |
| 字段校验明细 | 请求结构不符 | 按返回的 protovalidate 提示补字段 |
六、SDK 与生态兼容
- 官方 SDK:PHP(
mynaparrot/plugnmeet-sdk-php,Composer)与 JavaScript(plugnmeet-sdk,npm),封装了双头签名与全部/auth端点。 - 社区 SDK:Python 有社区维护版本;本文直接用标准库演示签名细节,便于排查 SDK 之外的自定义集成。
- BBB 兼容:
GET/POST {BASE}/{apiKey}/bigbluebutton/api/create|join|end|...,校验串规则与 BBB 一致(sha1(checksum)),已有 BBB 集成的系统改 baseURL 即可平迁,bbb_join_host配置项控制外发 join URL 域名。
七、常见问题
- 401 INVALID_TOKEN_OR_SIGNATURE 但头都带了:签名输入与发送体不一致(序列化差异)。签名与发送用同一份字节;Content-Type 必须是
application/json。 - create 返回字段校验错误:v2.5.3 强校验
metadata.room_features,从 4.1 节请求体起步再按需增改。 - 发送的 feature 开关没生效:能力集是
is_allow/is_active两级模型且部分字段名与请求不同,以getActiveRoomInfo回显为准核对。 - endRoom 后查询仍 active:异步关闭未完成,轮询数秒(实测约 6 秒)。
rooms:[]但 HTTP 200:空态返回status:false+NOT_FOUND,按数组判空。- token 拿到但进不了会:token 绑定
room_id且 10 分钟有效(exp-nbf);房间需在会中(is_running:1),过期重新调getJoinToken。
八、参考链接
- 官方 API 文档:https://www.plugnmeet.org/docs/intro(API 章节,与 v2.5.3 路由实测一致)
- 服务端源码路由定义:https://github.com/mynaparrot/plugNmeet-server(
pkg/app/router.go,tag v2.5.3) - 官方 PHP SDK:https://github.com/mynaparrot/plugnmeet-sdk-php JS SDK:npm
plugnmeet-sdk - 站内相关文档:《plugNmeet 2.5.3 介绍与选型指南》、《plugNmeet 2.5.3 配置参数详解》