聊天室訊息
從你的服務端向聊天室發訊息、查最近的訊息、撤回違規的訊息。聊天室訊息只推給此刻在聊天室裡的連線:不儲存離線訊息,不計未讀,不發離線推送,也不進入會話和訊息匯出。
| 要做什麼 | 介面 |
|---|---|
| 發系統通知、主播公告、禮物結算 | 傳送聊天室訊息,不能丟的用 "priority": "high" |
| 查聊天室最近的幾十條訊息 | 查詢最近的訊息 |
| 撤回違規訊息 | 撤回聊天室訊息 |
例如,以系統身份發一條高優先順序的通知:
curl -X POST "$IM_API/$ORG/$APP/chatrooms/100310941534519296/messages" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "type": "text", "body": { "text": "直播将在 5 分钟后开始" }, "priority": "high" }'服務端傳送時不檢查傳送者是否在聊天室裡、身份和禁言,規則見服務端傳送的規則。訊息的優先順序,以及訊息過多時的合併、限速和丟棄規則見聊天室管理。
與單聊、群聊訊息的區別
| 單聊、群聊訊息 | 聊天室訊息 | |
|---|---|---|
| 接收者 | 會話的成員,離線的裝置上線後補齊 | 此刻在聊天室裡的連線,離線期間的訊息收不到 |
| 儲存 | 儲存在會話中,可以查詢歷史訊息 | 只儲存最近的訊息(預設最近 50 條,最多 24 小時),低優先順序的訊息不儲存 |
| 訊息型別 | 見訊息型別 | text、image、voice、video、file、location、custom,body 和 ext 的格式與單聊、群聊訊息相同;不支援 tip 等系統專用的型別 |
| 大小上限 | 執行策略 max_message_body_bytes,預設 5 KB | 執行策略 max_chatroom_message_bytes,預設 2 KB,可設 256 位元組到 8 KB |
| 優先順序 | 沒有 | high、normal、low,訊息過多時按優先順序限流和丟棄 |
| 傳送者的資料 | 訊息中只有傳送者的使用者名稱 | 訊息中帶傳送時的暱稱、頭像和在聊天室中的身份,接收方不必逐個查詢 |
| 其他功能 | @、引用回覆、已讀回執、編輯、置頂、回應、離線推送 | 都不支援,訊息發出後只能撤回 |
| 防止重複傳送 | 用 client_msg_id 防止重複寫入 | 同一傳送者 5 分鐘內相同的 client_msg_id 只傳送一次;低優先順序的訊息不去重 |
傳送聊天室訊息
以某個使用者的身份或以系統的身份(沒有傳送者,客戶端通常顯示為系統通知)向聊天室傳送一條訊息。訊息立即推給此刻在聊天室裡的全部連線;普通和高優先順序的訊息同時寫入最近的訊息。訊息的 via 為 openapi,客戶端可以據此和 sender_role 顯示“官方”“房管”等標識,不應信任 ext 中自稱的身份。
/{org_name}/{app_name}/chatrooms/{room_id}/messages路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
room_id | String | 聊天室 ID |
請求體
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
from | String | 否 | 傳送者的使用者名稱,必須是已存在的使用者,不要求他在聊天室裡。省略時以系統身份傳送,訊息的 sender 為 null、sender_type 為 system |
client_msg_id | String | 否 | 你為這條訊息生成的唯一 ID,1 到 64 個可見 ASCII 字元,不能以 evt_、sys_ 開頭。同一傳送者(系統身份視為同一個傳送者)在同一聊天室中,5 分鐘內相同的 client_msg_id 只傳送一次,見下文的重複提交。省略時由服務端生成一個 UUID,不能防止重複傳送。低優先順序的訊息不去重 |
type | String | 是 | 訊息型別:text、image、voice、video、file、location 或 custom,見訊息型別 |
body | Object | 是 | 訊息體,格式由 type 決定,與單聊、群聊訊息相同,見訊息型別。圖片、語音、影片和檔案先以用途 attachment 上傳,再把地址寫進 body,服務端只檢查地址的格式 |
ext | Object | 否 | 擴充套件欄位,你自定義的 JSON 物件,規則見擴充套件欄位 ext。不需要時省略或傳 null |
priority | String | 否 | 優先順序:high、normal(預設)或 low,見訊息的優先順序與下發 |
type、body 和 ext 合計按服務端的 JSON 編碼(去掉空白、UTF-8 位元組)計算,不能超過執行策略 max_chatroom_message_bytes(預設 2048 位元組)。請求中不能帶 mentions、reply_to、push 等單聊、群聊訊息專用的欄位,帶了返回 400 invalid_argument。
請求示例
以系統身份傳送一條高優先順序的通知:
curl -X POST "$IM_API/$ORG/$APP/chatrooms/100310941534519296/messages" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_msg_id": "notice-20261004-001",
"type": "text",
"body": { "text": "直播将在 5 分钟后开始" },
"ext": { "kind": "live_notice" },
"priority": "high"
}'以主播(所有者)的身份傳送一條禮物訊息:
curl -X POST "$IM_API/$ORG/$APP/chatrooms/100310941534519296/messages" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"from": "zhangsan",
"client_msg_id": "gift-8f3a91",
"type": "custom",
"body": { "event": "gift", "gift_id": "rocket", "count": 1 },
"ext": { "combo": 3 },
"priority": "high"
}'響應
成功返回 201 Created,響應體為傳送的聊天室訊息物件,另加一個欄位:
| 欄位 | 型別 | 說明 |
|---|---|---|
dropped | Boolean | 低優先順序的訊息是否因限流被丟棄。新傳送的訊息為 false |
以系統身份傳送的響應:
{
"room_id": "100310941534519296",
"message_id": "100312324253941760",
"client_msg_id": "notice-20261004-001",
"sender": null,
"sender_type": "system",
"sender_nickname": null,
"sender_avatar_url": null,
"sender_role": null,
"type": "text",
"body": { "text": "直播将在 5 分钟后开始" },
"ext": { "kind": "live_notice" },
"priority": "high",
"via": "openapi",
"created_at": "2026-10-04T19:25:21.815Z",
"dropped": false
}以使用者身份傳送的響應:
{
"room_id": "100310941534519296",
"message_id": "100312466948358144",
"client_msg_id": "gift-8f3a91",
"sender": "zhangsan",
"sender_type": "user",
"sender_nickname": "张三",
"sender_avatar_url": "https://cdn.example.com/avatar/zhangsan.png",
"sender_role": "owner",
"type": "custom",
"body": { "event": "gift", "gift_id": "rocket", "count": 1 },
"ext": { "combo": 3 },
"priority": "high",
"via": "openapi",
"created_at": "2026-10-04T19:25:55.836Z",
"dropped": false
}重複提交:5 分鐘內用相同的 client_msg_id 重試時返回 200 OK,訊息不會再推送一次,響應中的 message_id 和 created_at 是第一次傳送的值。請以這兩個欄位為準:響應中的其他欄位取自這次請求,傳送者的欄位(sender 等)可能為空。
低優先順序的訊息被丟棄:超出聊天室每秒的訊息額度時返回 200 OK,dropped 為 true,message_id 和 created_at 為 null,訊息沒有發出。點贊這類訊息丟棄無妨,不需要重試:
{
"client_msg_id": null,
"created_at": null,
"dropped": true,
"message_id": null,
"priority": "low",
"room_id": "100311027198984192"
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | details.reason 為 unknown_type:不支援的訊息型別,包括 tip |
| 400 | invalid_argument | details.reason 為 invalid_body:body 或 ext 不符合要求,details.field 指出欄位 |
| 400 | invalid_argument | details.reason 為 invalid_client_msg_id:client_msg_id 不是 1 到 64 個可見 ASCII 字元 |
| 400 | invalid_argument | details.reason 為 reserved_client_msg_id:client_msg_id 以 evt_ 或 sys_ 開頭 |
| 400 | invalid_argument | details.reason 為 invalid_priority:priority 不是 high、normal、low 之一 |
| 403 | user_disabled | 傳送者已被平臺封禁,details.disabled_by 為 platform |
| 403 | chatroom_disabled | 聊天室已被封禁,details.disabled_by 為 tenant(你封禁的)或 platform(平臺封禁的) |
| 403 | message_rejected | 訊息被髮送前檢查拒絕:內容安全拒絕時 details.reason 為 sensitive_content(只按詞庫;第三方稽核在推送之後進行);發聊天室訊息前回撥拒絕時為 app_rejected 或 callback_unavailable,另有 details.app_reason,message 為接收端給出的提示 |
| 403 | app_unavailable | 應用處於只讀狀態,不能傳送訊息 |
| 404 | not_found | 聊天室不存在或已解散;from 指定的使用者不存在 |
| 413 | payload_too_large | 訊息超過應用的大小上限,details.max_bytes 為上限 |
| 429 | rate_limited | details.reason 為 room_send_rate:超過聊天室或應用每秒的訊息額度 |
| 500 | internal | details.reason 為 dependency_unavailable:訊息暫時無法推送,沒有發出。請按 Retry-After 響應頭等待後,用同一個 client_msg_id 重試 |
查詢最近的訊息
返回聊天室最近的訊息,按時間從早到晚排列,不要求任何使用者在聊天室裡。只包含普通和高優先順序的訊息,不含低優先順序的訊息和已撤回的訊息,最多保留 24 小時,儲存的條數由執行策略 chatroom_history_size 決定(預設 50 條),見最近的訊息。這不是完整的歷史記錄,不能向前翻頁。
/{org_name}/{app_name}/chatrooms/{room_id}/messages路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
room_id | String | 聊天室 ID |
查詢引數
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
limit | Number | 否 | 最多返回最近的多少條,正整數。預設和最大值都為執行策略 chatroom_history_size,超過時按它返回 |
一次響應中訊息合計不超過 1 MB,超出時捨去較早的幾條。
請求示例
curl -X GET "$IM_API/$ORG/$APP/chatrooms/100310941534519296/messages?limit=3" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK,items 中每項為一條聊天室訊息物件,按時間從早到晚排列;沒有訊息時為空陣列。
{
"items": [
{
"room_id": "100310941534519296",
"message_id": "100312466755420160",
"client_msg_id": "991d51c8-0e88-43d1-a830-ee3f160075cb",
"sender": "zhaoliu",
"sender_type": "user",
"sender_nickname": "赵六",
"sender_avatar_url": "https://cdn.example.com/avatar/zhaoliu.png",
"sender_role": "member",
"type": "text",
"body": { "text": "感谢大家的支持" },
"ext": null,
"priority": "normal",
"via": "openapi",
"created_at": "2026-10-04T19:25:55.790Z"
},
{
"room_id": "100310941534519296",
"message_id": "100312466948358144",
"client_msg_id": "gift-8f3a91",
"sender": "zhangsan",
"sender_type": "user",
"sender_nickname": "张三",
"sender_avatar_url": "https://cdn.example.com/avatar/zhangsan.png",
"sender_role": "owner",
"type": "custom",
"body": { "event": "gift", "gift_id": "rocket", "count": 1 },
"ext": { "combo": 3 },
"priority": "high",
"via": "openapi",
"created_at": "2026-10-04T19:25:55.836Z"
},
{
"room_id": "100310941534519296",
"message_id": "100312501224210432",
"client_msg_id": "c-97ff80f040e8",
"sender": "sunqi",
"sender_type": "user",
"sender_nickname": "孙七",
"sender_avatar_url": "https://cdn.example.com/avatar/sunqi.png",
"sender_role": "member",
"type": "text",
"body": { "text": "唱得太好了!" },
"ext": null,
"priority": "normal",
"via": "client",
"created_at": "2026-10-04T19:26:04.008Z"
}
]
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | limit 不是正整數 |
| 404 | not_found | 聊天室不存在或已解散 |
| 500 | internal | details.reason 為 dependency_unavailable:暫時無法讀取,按 Retry-After 響應頭等待後重試 |
撤回聊天室訊息
撤回聊天室中的一條訊息,不受傳送者和傳送時間的限制。撤回後,訊息從最近的訊息中刪除;線上成員實時收到撤回通知(recalled_by 為 null,role 為 server),客戶端把它從介面上移除。
撤回不能保證沒人看到
訊息已經推給了線上成員,撤回只是通知客戶端不再顯示。
不在最近的訊息中的訊息:低優先順序的訊息、已經超出儲存條數或 24 小時的訊息,以及已經撤回過的訊息,都不在最近的訊息中。服務端撤回它們時無法確認這條訊息是否存在,仍然照常推送撤回的通知,返回 changed 為 true;客戶端會忽略不認識的訊息 ID。因此重複撤回同一條訊息也會再推送一次通知,changed 同樣為 true。
被封禁的聊天室也可以撤回。
/{org_name}/{app_name}/chatrooms/{room_id}/messages/{message_id}/recall路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
room_id | String | 聊天室 ID |
message_id | String | 要撤回的訊息 ID |
請求體
請求體可以省略。
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
reason | String | 否 | 撤回原因,最長 256 個字元,不能包含控制字元。只記錄在控制檯的操作日誌中,不會展示給使用者 |
請求示例
curl -X POST "$IM_API/$ORG/$APP/chatrooms/100310941534519296/messages/100312501224210432/recall" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "含有违规内容"
}'響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
changed | Boolean | 是否推送了撤回的通知。只有極少數情況下(同一條訊息被幾個請求同時撤回)為 false |
{
"changed": true
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | reason 超過 256 個字元或包含控制字元 |
| 404 | not_found | 聊天室不存在或已解散;message_id 的格式不對 |
| 500 | internal | details.reason 為 dependency_unavailable:暫時無法撤回,按 Retry-After 響應頭等待後重試 |
服務端傳送的規則
使用者在客戶端傳送聊天室訊息要滿足:
- 發出訊息的這條連線在聊天室裡;
- 沒有被聊天室禁言;開啟了全員禁言時,是所有者、管理員或在白名單中;
- 沒有被全域性禁言;
- 高優先順序的訊息只有所有者和管理員能發;
- 每個使用者每秒最多 5 條(突發 10 條)。
你的服務端以某個使用者或系統的身份傳送時,以上都不檢查:任何傳送者都能發高優先順序的訊息,也不檢查附件地址是否符合 media_url_only。服務端只檢查:
| 檢查 | 不透過時 |
|---|---|
| 訊息的型別、內容和大小符合要求 | 400 invalid_argument、413 payload_too_large |
傳送者(from)存在且未被刪除 | 404 not_found |
| 傳送者沒有被平臺封禁。被你的應用封禁的使用者仍可以作為傳送者 | 403 user_disabled |
| 聊天室存在且沒有解散 | 404 not_found |
| 聊天室沒有被封禁(包括被你封禁的) | 403 chatroom_disabled |
| 應用不是隻讀狀態 | 403 app_unavailable |
| 按聊天室、按應用的傳送限流 | 普通和高優先順序返回 429 rate_limited;低優先順序的訊息被丟棄 |
限流:客戶端和服務端傳送的訊息合計計算,規則見訊息的優先順序與下發:
| 限額 | 數值 | 超出時 |
|---|---|---|
| 每個聊天室每秒的普通和低優先順序訊息 | 執行策略 chatroom_msg_per_second,預設 40 條,可設 1 到 200 | 普通訊息返回 429 rate_limited,details.reason 為 room_send_rate;低優先順序的訊息被丟棄,響應中 dropped 為 true |
| 每個聊天室每秒的高優先順序訊息 | 20 條 | 429 rate_limited,details.reason 為 room_send_rate |
| 應用全部聊天室每秒的訊息 | 配額 chatroom_msg_per_sec_limit,預設 2000 條,三種優先順序都計入 | 同上,details.reason 同樣為 room_send_rate |
聊天室訊息不計入單聊、群聊的訊息配額 msg_per_min_limit。傳送請求和其他 OpenAPI 請求一樣計入應用每秒的呼叫次數。
{
"error": {
"code": "rate_limited",
"message": "聊天室消息太多,请稍后再试",
"details": { "reason": "room_send_rate", "retry_after_seconds": 1 },
"request_id": "KK4Z3DWPMCYBGRI7SYJK3OQQOL"
}
}傳送前檢查:透過以上檢查後,訊息依次經過兩項檢查,合計最多 500 毫秒:
| 檢查 | 規則 | 不透過時 |
|---|---|---|
| 內容安全 | 服務端傳送的預設只按平臺規則;為聊天室訊息開啟了服務端提交的內容也檢查時,還按你的詞庫和第三方稽核。最多 200 毫秒,第三方稽核超時或出錯時放行、之後補審;低優先順序的只按詞庫 | 403 message_rejected(sensitive_content 等,見呼叫方看到的錯誤);命中替換規則的按替換後的內容傳送 |
| 發聊天室訊息前回撥 | 預設只對客戶端傳送的呼叫;vias 包含 openapi 時服務端傳送的也呼叫。在剩餘時間內等待響應 | 拒絕時 403 message_rejected(app_rejected);超時或失敗且策略為“拒絕”時同樣返回(callback_unavailable);改寫的按改寫後的 body、ext 傳送,見操作方收到的錯誤 |
響應中的 body、ext 是替換、改寫之後實際傳送的內容。使用者在客戶端傳送的訊息被改寫時,長連線上 chatroom.send 的回覆中同樣帶改寫後的 body 和 ext,客戶端據此更新本地顯示的訊息。
資料結構
聊天室訊息物件
推送給客戶端的訊息、傳送的響應和最近的訊息中,每條訊息的格式相同。
| 欄位 | 型別 | 說明 |
|---|---|---|
room_id | String | 聊天室 ID |
message_id | String | 訊息 ID,由服務端生成 |
client_msg_id | String | 傳送方給出的 client_msg_id;服務端傳送時沒有給出的,為服務端生成的 UUID;客戶端傳送的低優先順序訊息可以沒有,為 null |
sender | String | 傳送者的使用者名稱;系統訊息為 null |
sender_type | String | 傳送者型別:user 使用者,system 系統 |
sender_nickname | String | 傳送時傳送者的暱稱,之後不隨資料的變化而更新;系統訊息為 null |
sender_avatar_url | String | 傳送時傳送者的頭像地址;系統訊息為 null |
sender_role | String | 傳送時傳送者在聊天室中的身份:owner、admin 或 member;系統訊息為 null |
type | String | 訊息型別,見訊息型別 |
body | Object | 訊息體 |
ext | Object | 擴充套件欄位,沒有時為 null |
priority | String | 優先順序:high、normal 或 low |
via | String | 傳送入口:client 使用者在客戶端傳送,openapi 你的服務端傳送,console 在控制檯傳送,system 由本服務自動傳送 |
created_at | String | 傳送時間。同一聊天室中訊息的時間只是大致有序,客戶端按到達的順序顯示即可 |
{
"room_id": "100310941534519296",
"message_id": "100312324354605056",
"client_msg_id": "b1f3c0de-5e7a-4f55-9c1d-2a8e6f0b9d11",
"sender": "lisi",
"sender_type": "user",
"sender_nickname": "李四",
"sender_avatar_url": "https://cdn.example.com/avatar/lisi.png",
"sender_role": "admin",
"type": "text",
"body": { "text": "欢迎大家,开播后请文明发言" },
"ext": null,
"priority": "normal",
"via": "openapi",
"created_at": "2026-10-04T19:25:21.839Z"
}