swagger: "2.0" info: title: HY Gateway Service API version: "1.0.0" description: | gateway-service 对外暴露 HTTP + JSON API。 `/api/v1/**` 业务接口统一返回 `code/message/request_id/data` 外壳,并通过 `X-Request-ID` 贯穿 HTTP 响应和内部 gRPC RequestMeta。 `/healthz/**` 是健康检查接口,不使用业务响应外壳。 host: localhost:13000 basePath: / schemes: - http consumes: - application/json produces: - application/json tags: - name: health description: Gateway 进程和依赖探测。 - name: auth description: 登录、刷新、登出和密码初始化。 - name: tencent-im description: 腾讯云 IM 登录票据和服务端回调入口。 - name: tencent-rtc description: 腾讯 RTC 语音进房票据入口。 - name: users description: 当前展示短号查询和变更。 - name: rooms description: 房间命令入口,最终由 room-service 执行。 securityDefinitions: BearerAuth: type: apiKey name: Authorization in: header description: 使用 `Bearer `;JWT 使用 HS256,claims 必须包含数值型 `user_id`。 parameters: RequestIDHeader: name: X-Request-ID in: header required: false type: string description: 可选追踪 ID;未传时 gateway 自动生成,并返回在响应 header 和 JSON `request_id`。该字段不是幂等键,房间命令重试幂等使用请求体 `command_id`。 DisplayUserIDPath: name: display_user_id in: path required: true type: string description: 当前有效展示短号。 TencentIMSDKAppID: name: SdkAppid in: query required: true type: integer format: int64 description: 腾讯云 IM 回调携带的 SDKAppID;当前入口接受 `SdkAppid` 查询名。 TencentIMCallbackCommand: name: CallbackCommand in: query required: false type: string enum: - Group.CallbackBeforeApplyJoinGroup - Group.CallbackBeforeSendMsg description: 腾讯云 IM 回调命令;如果 query 和 body 同时存在,二者必须一致。 TencentIMCallbackAuthToken: name: CallbackAuthToken in: query required: false type: string description: 腾讯云 IM 回调鉴权 token;也可通过 `X-Tencent-IM-Callback-Token` header 传入。 TencentIMCallbackTokenHeader: name: X-Tencent-IM-Callback-Token in: header required: false type: string description: 腾讯云 IM 回调鉴权 token header。 responses: BadRequest: description: 请求体不是合法 JSON,或下游返回非法参数;常见 `code` 为 `INVALID_JSON`、`INVALID_ARGUMENT`、`DISPLAY_USER_ID_INVALID`。 schema: $ref: "#/definitions/ErrorEnvelope" Unauthorized: description: 未通过 access token 校验,或下游返回认证失败。 schema: $ref: "#/definitions/ErrorEnvelope" Forbidden: description: 已认证但被禁用、封禁或无权限。 schema: $ref: "#/definitions/ErrorEnvelope" NotFound: description: 下游实体不存在。 schema: $ref: "#/definitions/ErrorEnvelope" Conflict: description: 下游唯一键、状态、租约或冷却期冲突。 schema: $ref: "#/definitions/ErrorEnvelope" Internal: description: gateway 或下游返回不可细分的内部错误。 schema: $ref: "#/definitions/ErrorEnvelope" UpstreamError: description: gateway 调内部服务失败,或内部服务返回不可映射错误。 schema: $ref: "#/definitions/ErrorEnvelope" paths: /healthz/live: get: tags: - health summary: 进程存活探测 operationId: gatewayLive responses: "200": description: Gateway HTTP runtime 正在服务。 schema: $ref: "#/definitions/HealthResponse" "500": description: Gateway HTTP runtime 不可用。 schema: $ref: "#/definitions/HealthResponse" /healthz/ready: get: tags: - health summary: 接流量就绪探测 operationId: gatewayReady responses: "200": description: Gateway 可接新请求。 schema: $ref: "#/definitions/HealthResponse" "503": description: Gateway 不应接新请求,失败详情在 `checks`。 schema: $ref: "#/definitions/HealthResponse" /api/v1/auth/password/login: post: tags: - auth summary: 短号密码登录 operationId: loginPassword parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/LoginPasswordRequest" responses: "200": description: 登录成功,`data` 返回 token 集合。 schema: $ref: "#/definitions/AuthTokenEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/auth/third-party/login: post: tags: - auth summary: 三方登录或注册 operationId: loginThirdParty parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/LoginThirdPartyRequest" responses: "200": description: 登录或注册成功,`data` 返回 token 集合和 `is_new_user`。 schema: $ref: "#/definitions/AuthTokenEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/auth/password/set: post: tags: - auth summary: 已登录用户首次设置密码 operationId: setPassword security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/SetPasswordRequest" responses: "200": description: 密码设置成功。 schema: $ref: "#/definitions/PasswordSetEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/auth/token/refresh: post: tags: - auth summary: 刷新 token operationId: refreshToken parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/RefreshTokenRequest" responses: "200": description: 刷新成功,`data` 返回新的 token 集合。 schema: $ref: "#/definitions/AuthTokenEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/auth/logout: post: tags: - auth summary: 登出并失效 refresh session operationId: logout parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/LogoutRequest" responses: "200": description: 登出处理完成。 schema: $ref: "#/definitions/LogoutEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/im/usersig: get: tags: - tencent-im summary: 获取腾讯云 IM UserSig operationId: issueTencentIMUserSig security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" responses: "200": description: 签发成功,`data.user_id` 使用内部长 `user_id` 的十进制字符串。 schema: $ref: "#/definitions/TencentIMUserSigEnvelope" "401": $ref: "#/responses/Unauthorized" "500": description: 腾讯云 IM SDKAppID、SecretKey 或 TTL 配置缺失,fail-closed。 schema: $ref: "#/definitions/ErrorEnvelope" /api/v1/rtc/token: post: tags: - tencent-rtc summary: 获取腾讯 RTC 进房 UserSig operationId: issueTencentRTCToken description: | gateway 使用 access token 中的内部 `user_id` 签发腾讯 RTC UserSig,并在签发前调用 room-service `VerifyRoomPresence`。 当前只支持 TRTC 字符串房间 `strRoomId`,客户端不能把 `room_id` 转成数字 `roomId`。 security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/TencentRTCTokenRequest" responses: "200": description: 签发成功,`data.user_id` 和 `data.rtc_user_id` 都是内部长 `user_id` 的十进制字符串。 schema: $ref: "#/definitions/TencentRTCTokenEnvelope" "400": description: "`room_id` 为空或不满足 `^[A-Za-z0-9_-]{1,48}$`。" schema: $ref: "#/definitions/ErrorEnvelope" "401": $ref: "#/responses/Unauthorized" "403": description: 用户不在房间、已被踢出或被封禁,gateway 不返回 UserSig。 schema: $ref: "#/definitions/ErrorEnvelope" "404": description: room-service guard 返回 `room_not_found`。 schema: $ref: "#/definitions/ErrorEnvelope" "500": description: 腾讯 RTC 未启用、SDKAppID、SecretKey、TTL 或固定策略配置缺失,fail-closed。 schema: $ref: "#/definitions/ErrorEnvelope" "502": $ref: "#/responses/UpstreamError" /api/v1/tencent-im/callback: post: tags: - tencent-im summary: 腾讯云 IM 服务端回调 operationId: handleTencentIMCallback description: | 该接口不使用项目业务 envelope,直接返回腾讯云 IM 要求的 `ActionStatus/ErrorCode/ErrorInfo`。 当前支持入群前守卫 `Group.CallbackBeforeApplyJoinGroup` 和发言前守卫 `Group.CallbackBeforeSendMsg`。 白名单外回调在通过来源校验和 SDKAppID 校验后返回允许,避免阻断腾讯云新增回调。 parameters: - $ref: "#/parameters/TencentIMSDKAppID" - $ref: "#/parameters/TencentIMCallbackCommand" - $ref: "#/parameters/TencentIMCallbackAuthToken" - $ref: "#/parameters/TencentIMCallbackTokenHeader" - name: body in: body required: false schema: $ref: "#/definitions/TencentIMCallbackRequest" responses: "200": description: 腾讯云 IM 回调处理结果;业务拒绝也返回 HTTP 200,通过 `ErrorCode=1` 表示拒绝。 schema: $ref: "#/definitions/TencentIMCallbackResponse" "405": description: 非 POST 请求会返回腾讯云原生结构,`ErrorCode=1`。 schema: $ref: "#/definitions/TencentIMCallbackResponse" /api/v1/users/by-display-user-id/{display_user_id}: get: tags: - users summary: 通过当前展示短号解析用户 operationId: resolveDisplayUserID parameters: - $ref: "#/parameters/RequestIDHeader" - $ref: "#/parameters/DisplayUserIDPath" responses: "200": description: 解析成功,`data` 返回短号归属。 schema: $ref: "#/definitions/UserIdentityEnvelope" "400": $ref: "#/responses/BadRequest" "404": $ref: "#/responses/NotFound" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/users/me/identity: get: tags: - users summary: 查询当前用户展示短号状态 operationId: getMyIdentity security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" responses: "200": description: 查询成功,`data` 返回当前用户短号状态。 schema: $ref: "#/definitions/UserIdentityEnvelope" "401": $ref: "#/responses/Unauthorized" "404": $ref: "#/responses/NotFound" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/users/me/profile/update: post: tags: - users summary: 修改当前用户基础资料 operationId: updateMyProfile description: 只修改 `username`、`avatar`、`birth`;国家修改必须走独立国家接口。 security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/UpdateUserProfileRequest" responses: "200": description: 修改成功,`data` 返回最新用户资料。 schema: $ref: "#/definitions/UserProfileEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "404": $ref: "#/responses/NotFound" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/users/me/country/change: post: tags: - users summary: 修改当前用户国家 operationId: changeMyCountry description: 国家修改单独写变更日志;同一用户按滚动 30 天冷却窗口只能成功修改一次。 security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/ChangeUserCountryRequest" responses: "200": description: 修改成功,`data.next_country_change_allowed_at_ms` 返回下一次可修改时间。 schema: $ref: "#/definitions/UserProfileEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/users/me/display-id/change: post: tags: - users summary: 修改当前用户默认短号 operationId: changeMyDisplayUserID security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/ChangeDisplayUserIDRequest" responses: "200": description: 修改成功,`data` 返回最新短号状态。 schema: $ref: "#/definitions/UserIdentityEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/users/me/display-id/pretty/apply: post: tags: - users summary: 申请临时靓号 operationId: applyMyPrettyDisplayUserID security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/ApplyPrettyDisplayUserIDRequest" responses: "200": description: 申请成功,`data` 返回最新短号状态和租约 ID。 schema: $ref: "#/definitions/UserIdentityEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/create: post: tags: - rooms summary: 创建房间 operationId: createRoom description: | gateway 从 access token 取当前 `user_id` 写入 room-service `RequestMeta.actor_user_id`,room-service 由该 actor 确定 owner 和默认 host。 请求体不接收 `owner_user_id` 或 `host_user_id`;房间命令重试幂等使用 `command_id`,不是 `X-Request-ID`。 security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/CreateRoomRequest" responses: "200": description: 创建成功,`data` 返回房间快照。 schema: $ref: "#/definitions/CreateRoomEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/join: post: tags: - rooms summary: 加入房间 operationId: joinRoom security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/JoinRoomRequest" responses: "200": description: 加入成功,`data` 返回用户房间态和房间快照。 schema: $ref: "#/definitions/JoinRoomEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/leave: post: tags: - rooms summary: 离开房间 operationId: leaveRoom security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/LeaveRoomRequest" responses: "200": description: 离房成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/LeaveRoomEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/mic/up: post: tags: - rooms summary: 上麦 operationId: micUp security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/MicUpRequest" responses: "200": description: 上麦成功,`data` 返回目标麦位和最新房间快照。 schema: $ref: "#/definitions/MicUpEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/mic/down: post: tags: - rooms summary: 下麦 operationId: micDown security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/MicDownRequest" responses: "200": description: 下麦成功,`data` 返回目标麦位和最新房间快照。 schema: $ref: "#/definitions/MicDownEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/mic/change: post: tags: - rooms summary: 调整麦位 operationId: changeMicSeat security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/ChangeMicSeatRequest" responses: "200": description: 调整成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/ChangeMicSeatEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/mic/publishing/confirm: post: tags: - rooms summary: 确认 RTC 音频发布成功 operationId: confirmMicPublishing security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/ConfirmMicPublishingRequest" responses: "200": description: 确认成功或旧事件被安全忽略,`data` 返回最新房间快照。 schema: $ref: "#/definitions/ConfirmMicPublishingEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/mic/lock: post: tags: - rooms summary: 锁定或解锁麦位 operationId: setMicSeatLock security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/SetMicSeatLockRequest" responses: "200": description: 锁麦状态修改成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/SetMicSeatLockEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/chat/enabled: post: tags: - rooms summary: 开启或关闭房间公屏 operationId: setChatEnabled security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/SetChatEnabledRequest" responses: "200": description: 公屏开关修改成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/SetChatEnabledEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/admin/set: post: tags: - rooms summary: 添加或移除房间管理员 operationId: setRoomAdmin security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/SetRoomAdminRequest" responses: "200": description: 管理员集合修改成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/SetRoomAdminEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/host/transfer: post: tags: - rooms summary: 转移房间主持人 operationId: transferRoomHost security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/TransferRoomHostRequest" responses: "200": description: 主持人转移成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/TransferRoomHostEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/user/mute: post: tags: - rooms summary: 设置房间内禁言 operationId: muteUser security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/MuteUserRequest" responses: "200": description: 禁言状态修改成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/MuteUserEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/user/kick: post: tags: - rooms summary: 踢出房间用户 operationId: kickUser security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/KickUserRequest" responses: "200": description: 踢人成功,`data` 返回最新房间快照。 schema: $ref: "#/definitions/KickUserEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/user/unban: post: tags: - rooms summary: 解除房间 ban operationId: unbanUser security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/UnbanUserRequest" responses: "200": description: 解封成功,`data` 返回最新房间快照,不自动恢复 presence、麦位或管理员身份。 schema: $ref: "#/definitions/UnbanUserEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" /api/v1/rooms/gift/send: post: tags: - rooms summary: 发送礼物 operationId: sendGift security: - BearerAuth: [] parameters: - $ref: "#/parameters/RequestIDHeader" - name: body in: body required: true schema: $ref: "#/definitions/SendGiftRequest" responses: "200": description: 送礼成功,`data` 返回账单凭证、热度、本地礼物榜和房间快照。 schema: $ref: "#/definitions/SendGiftEnvelope" "400": $ref: "#/responses/BadRequest" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/Forbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" definitions: GatewayOKEnvelopeBase: type: object required: - code - message - request_id properties: code: type: string enum: - OK message: type: string enum: - ok request_id: type: string description: gateway 业务 API 成功响应外壳。 ErrorEnvelope: type: object required: - code - message - request_id properties: code: type: string enum: - INVALID_JSON - UNAUTHORIZED - UPSTREAM_ERROR - INTERNAL_ERROR - INVALID_ARGUMENT - RATE_LIMITED - AUTH_FAILED - SESSION_EXPIRED - SESSION_REVOKED - PASSWORD_ALREADY_SET - DISPLAY_USER_ID_INVALID - DISPLAY_USER_ID_EXISTS - DISPLAY_USER_ID_COOLDOWN - COUNTRY_CHANGE_COOLDOWN - DISPLAY_USER_ID_NOT_FOUND - DISPLAY_USER_ID_PRETTY_NOT_AVAILABLE - DISPLAY_USER_ID_PRETTY_ACTIVE - DISPLAY_USER_ID_LEASE_EXPIRED - DISPLAY_USER_ID_PAYMENT_REQUIRED - USER_DISABLED - PERMISSION_DENIED - NOT_FOUND message: type: string enum: - invalid request body - unauthorized - upstream service error - internal error - invalid argument - rate limited - authentication failed - conflict - permission denied - not found request_id: type: string description: gateway 业务 API 失败响应外壳;失败响应不返回 `data`。 HealthResponse: type: object properties: status: type: string enum: - ok - fail service: type: string example: gateway-service node_id: type: string time_unix_ms: type: integer format: int64 checks: type: array items: $ref: "#/definitions/HealthCheck" HealthCheck: type: object properties: name: type: string example: room_grpc status: type: string enum: - ok - fail message: type: string LoginPasswordRequest: type: object properties: display_user_id: type: string password: type: string device_id: type: string LoginThirdPartyRequest: type: object description: 三方登录即注册;首次注册时资料字段写入 user-service users 主记录。`ip`、`user_agent` 和 `country_by_ip` 由 gateway/服务端上下文生成,不接受客户端 JSON。 properties: provider: type: string example: google credential: type: string username: type: string maxLength: 64 gender: type: string maxLength: 32 country: type: string maxLength: 3 pattern: "^[A-Za-z]{2,3}$" description: 国家主数据 country_code,支持 2 到 3 位英文,服务端会转大写并要求 active。 invite_code: type: string maxLength: 64 description: 可选邀请码。 device_id: type: string maxLength: 128 device: type: string maxLength: 128 os_version: type: string maxLength: 64 avatar: type: string maxLength: 512 description: 绝对 http/https URL。 birth: type: string description: yyyy-mm-dd。 app_version: type: string maxLength: 64 build_number: type: string maxLength: 64 source: type: string maxLength: 64 install_channel: type: string maxLength: 64 campaign: type: string maxLength: 128 platform: type: string maxLength: 16 enum: - android - ios language: type: string maxLength: 32 description: BCP 47 language tag subset,例如 en-US。 timezone: type: string maxLength: 64 description: IANA timezone name,例如 America/Los_Angeles。 SetPasswordRequest: type: object properties: password: type: string RefreshTokenRequest: type: object properties: refresh_token: type: string device_id: type: string LogoutRequest: type: object properties: refresh_token: type: string session_id: type: string AuthTokenData: type: object properties: user_id: type: integer format: int64 display_user_id: type: string default_display_user_id: type: string display_user_id_kind: type: string display_user_id_expires_at_ms: type: integer format: int64 session_id: type: string access_token: type: string refresh_token: type: string expires_in_sec: type: integer format: int64 token_type: type: string example: Bearer is_new_user: type: boolean PasswordSetData: type: object properties: password_set: type: boolean LogoutData: type: object properties: revoked: type: boolean TencentIMUserSigData: type: object properties: sdk_app_id: type: integer format: int64 user_id: type: string description: 腾讯云 IM identifier;当前固定使用内部长 `user_id` 的十进制字符串。 user_sig: type: string expire_at_ms: type: integer format: int64 description: 客户端登录腾讯云 IM SDK 所需票据。 TencentRTCTokenRequest: type: object required: - room_id properties: room_id: type: string pattern: "^[A-Za-z0-9_-]{1,48}$" maxLength: 48 description: 内部房间 ID,同时作为腾讯 RTC `strRoomId` 使用。 TencentRTCTokenData: type: object properties: sdk_app_id: type: integer format: int64 user_id: type: string description: 腾讯 RTC UserID;当前固定使用内部长 `user_id` 的十进制字符串。 rtc_user_id: type: string description: 与 `user_id` 相同,帮助客户端显式区分业务身份和 RTC SDK 身份。 user_sig: type: string description: 腾讯 RTC UserSig,客户端用它进入腾讯 RTC;不是 SecretKey。 expire_at_ms: type: integer format: int64 room_id: type: string description: 内部房间 ID。 rtc_room_id: type: string description: 腾讯 RTC 字符串房间 ID,值等于 `room_id`。 rtc_room_id_type: type: string enum: - string str_room_id: type: string description: 客户端调用 TRTC enterRoom 时使用的 `strRoomId`。 app_scene: type: string enum: - voice_chat_room role: type: string enum: - audience description: 首版固定返回 audience;上麦成功后客户端再切换发布角色。 description: 客户端进入腾讯 RTC 语音房所需票据和字符串房间映射。 TencentIMCallbackRequest: type: object properties: CallbackCommand: type: string enum: - Group.CallbackBeforeApplyJoinGroup - Group.CallbackBeforeSendMsg GroupId: type: string description: 映射为内部 `room_id`。 Requestor_Account: type: string description: 入群申请用户;必须是内部长 `user_id` 的十进制字符串。 From_Account: type: string description: 发言用户;必须是内部长 `user_id` 的十进制字符串。 Operator_Account: type: string description: 腾讯云 IM 回调操作者账号字段。 TencentIMCallbackResponse: type: object properties: ActionStatus: type: string enum: - OK ErrorInfo: type: string ErrorCode: type: integer format: int32 enum: - 0 - 1 description: 腾讯云 IM 原生回调响应;`ErrorCode=0` 允许,`ErrorCode=1` 拒绝本次入群或发言。 UserIdentityData: type: object properties: user_id: type: integer format: int64 display_user_id: type: string status: type: string default_display_user_id: type: string display_user_id_kind: type: string display_user_id_expires_at_ms: type: integer format: int64 lease_id: type: string UserProfileData: type: object properties: user_id: type: integer format: int64 display_user_id: type: string default_display_user_id: type: string display_user_id_kind: type: string display_user_id_expires_at_ms: type: integer format: int64 username: type: string gender: type: string country: type: string maxLength: 3 description: 用户选择的国家主数据 country_code。 country_id: type: integer format: int64 description: 国家主数据内部 ID;0 表示未命中国家表。 country_name: type: string country_display_name: type: string region_id: type: integer format: int64 description: 国家映射出的区域 ID;0 表示无区域归属。 region_code: type: string region_name: type: string avatar: type: string birth: type: string description: yyyy-mm-dd。 language: type: string updated_at_ms: type: integer format: int64 next_country_change_allowed_at_ms: type: integer format: int64 UpdateUserProfileRequest: type: object properties: username: type: string avatar: type: string birth: type: string description: yyyy-mm-dd;传空字符串表示清空生日。 ChangeUserCountryRequest: type: object properties: country: type: string maxLength: 3 pattern: "^[A-Za-z]{2,3}$" description: 国家主数据 country_code,服务端会转大写并要求 active。 ChangeDisplayUserIDRequest: type: object properties: new_display_user_id: type: string reason: type: string ApplyPrettyDisplayUserIDRequest: type: object properties: pretty_display_user_id: type: string lease_duration_ms: type: integer format: int64 payment_receipt_id: type: string CreateRoomRequest: type: object required: - room_id - seat_count - mode properties: room_id: type: string pattern: "^[A-Za-z0-9_-]{1,48}$" maxLength: 48 description: 同时满足腾讯 IM GroupID 和 RTC strRoomId 限制的业务房间 ID。 command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 seat_count: type: integer format: int32 minimum: 1 description: 麦位数量,必须大于 0。 mode: type: string minLength: 1 description: 房间模式,不能为空;当前服务只保存并透出该值,不在 gateway 做枚举分发。 JoinRoomRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 role: type: string LeaveRoomRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 MicUpRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 seat_no: type: integer format: int32 MicDownRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 reason: type: string description: 主动下麦可为空;系统自动下麦会使用 publish_timeout 等稳定原因。 ChangeMicSeatRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 seat_no: type: integer format: int32 ConfirmMicPublishingRequest: type: object required: - room_id - mic_session_id - room_version - event_time_ms properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一确认事件必须复用该值。 target_user_id: type: integer format: int64 description: 为空时默认确认当前登录用户;RTC webhook 编排可显式传目标用户。 mic_session_id: type: string room_version: type: integer format: int64 event_time_ms: type: integer format: int64 source: type: string description: 例如 client 或 rtc_webhook。 SetMicSeatLockRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 seat_no: type: integer format: int32 locked: type: boolean SetChatEnabledRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 enabled: type: boolean SetRoomAdminRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 enabled: type: boolean TransferRoomHostRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 MuteUserRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 muted: type: boolean KickUserRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 UnbanUserRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 SendGiftRequest: type: object properties: room_id: type: string command_id: type: string description: 房间命令幂等键;客户端重试同一业务动作必须复用该值。未传时 gateway 自动生成新值,仅保证本次请求可执行,不保证后续 HTTP 重试幂等。 target_user_id: type: integer format: int64 gift_id: type: string gift_count: type: integer format: int32 CommandResult: type: object properties: applied: type: boolean room_version: type: integer format: int64 server_time_ms: type: integer format: int64 RoomUser: type: object properties: user_id: type: integer format: int64 role: type: string joined_at_ms: type: integer format: int64 last_seen_at_ms: type: integer format: int64 SeatState: type: object properties: seat_no: type: integer format: int32 user_id: type: integer format: int64 locked: type: boolean publish_state: type: string enum: - pending_publish - publishing - idle description: pending_publish 表示业务占麦成功但 RTC 尚未确认发流;publishing 表示已确认发布音频。 mic_session_id: type: string publish_deadline_ms: type: integer format: int64 mic_session_room_version: type: integer format: int64 last_publish_event_time_ms: type: integer format: int64 RankItem: type: object properties: user_id: type: integer format: int64 score: type: integer format: int64 gift_value: type: integer format: int64 updated_at_ms: type: integer format: int64 RoomSnapshot: type: object properties: room_id: type: string owner_user_id: type: integer format: int64 host_user_id: type: integer format: int64 mode: type: string status: type: string chat_enabled: type: boolean mic_seats: type: array items: $ref: "#/definitions/SeatState" online_users: type: array items: $ref: "#/definitions/RoomUser" admin_user_ids: type: array items: type: integer format: int64 ban_user_ids: type: array items: type: integer format: int64 mute_user_ids: type: array items: type: integer format: int64 gift_rank: type: array items: $ref: "#/definitions/RankItem" room_ext: type: object additionalProperties: type: string heat: type: integer format: int64 version: type: integer format: int64 CreateRoomResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" JoinRoomResponse: type: object properties: result: $ref: "#/definitions/CommandResult" user: $ref: "#/definitions/RoomUser" room: $ref: "#/definitions/RoomSnapshot" LeaveRoomResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" MicUpResponse: type: object properties: result: $ref: "#/definitions/CommandResult" seat_no: type: integer format: int32 room: $ref: "#/definitions/RoomSnapshot" mic_session_id: type: string publish_deadline_ms: type: integer format: int64 MicDownResponse: type: object properties: result: $ref: "#/definitions/CommandResult" seat_no: type: integer format: int32 room: $ref: "#/definitions/RoomSnapshot" ChangeMicSeatResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" ConfirmMicPublishingResponse: type: object properties: result: $ref: "#/definitions/CommandResult" seat_no: type: integer format: int32 room: $ref: "#/definitions/RoomSnapshot" SetMicSeatLockResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" SetChatEnabledResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" SetRoomAdminResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" TransferRoomHostResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" MuteUserResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" KickUserResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" UnbanUserResponse: type: object properties: result: $ref: "#/definitions/CommandResult" room: $ref: "#/definitions/RoomSnapshot" SendGiftResponse: type: object properties: result: $ref: "#/definitions/CommandResult" billing_receipt_id: type: string room_heat: type: integer format: int64 gift_rank: type: array items: $ref: "#/definitions/RankItem" room: $ref: "#/definitions/RoomSnapshot" AuthTokenEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/AuthTokenData" PasswordSetEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/PasswordSetData" LogoutEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/LogoutData" TencentIMUserSigEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/TencentIMUserSigData" TencentRTCTokenEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/TencentRTCTokenData" UserIdentityEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/UserIdentityData" UserProfileEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/UserProfileData" CreateRoomEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/CreateRoomResponse" JoinRoomEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/JoinRoomResponse" LeaveRoomEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/LeaveRoomResponse" MicUpEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/MicUpResponse" MicDownEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/MicDownResponse" ChangeMicSeatEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/ChangeMicSeatResponse" ConfirmMicPublishingEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/ConfirmMicPublishingResponse" SetMicSeatLockEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/SetMicSeatLockResponse" SetChatEnabledEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/SetChatEnabledResponse" SetRoomAdminEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/SetRoomAdminResponse" TransferRoomHostEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/TransferRoomHostResponse" MuteUserEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/MuteUserResponse" KickUserEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/KickUserResponse" UnbanUserEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/UnbanUserResponse" SendGiftEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" - type: object properties: data: $ref: "#/definitions/SendGiftResponse"