通話管理
本頁介紹你的服務端如何查詢本應用的通話、強制結束通話、把成員移出通話,以及檢視每天的通話統計。通話的流程、狀態、結束原因和通話物件的欄位見音視訊通話。
| 要做什麼 | 介面 |
|---|---|
在客服、問診等業務中按使用者或時間查通話,結合 ext(如訂單號)核對業務記錄 | 查詢通話列表、查詢通話詳情 |
| 發現違規時強制結束通話 | 結束通話 |
| 把某個成員移出群通話 | 把成員移出通話 |
| 在發起業務操作前確認使用者沒在通話 | 查詢使用者正在進行的通話 |
| 每天核對通話數量和歷史分鐘數 | 查詢通話統計。實際扣費以控制檯的音影片流水為準 |
說明:
- 不受執行策略
rtc_enabled限制:應用關閉音影片後,仍然可以查詢和結束通話;應用處於只讀狀態時同樣可用。 - 不能發起通話或代使用者接聽:通話需要使用者的裝置連線媒體服務,只能由客戶端發起和接聽。
- 通話資料在結束 180 天后刪除,之後查詢不到;需要長期儲存的,請透過事件回撥的
rtc.call_ended儲存到你的業務系統。 - 控制檯應用詳情的“音影片”頁面也可以查詢通話、檢視統計,
owner和admin可以在其中結束通話和移出成員。
查詢通話列表
按條件查詢本應用的通話,按發起時間從新到舊排列,包括進行中和已結束的通話。列表中的每一項不含成員,需要成員時查詢通話詳情。
/{org_name}/{app_name}/calls路徑引數
org_name、app_name 見接入概述。
查詢引數
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
username | String | 否 | 只返回這個使用者參與過的通話,即他是成員的通話,包括他未接聽、拒絕的。使用者不存在時返回空列表 |
group_id | String | 否 | 只返回這個群的群通話 |
type | String | 否 | 通話型別:single 或 group |
status | String | 否 | 通話狀態:ringing、active 或 ended。查詢進行中的通話時分別查詢 ringing 和 active |
start_time | String | 否 | 只返回發起時間不早於它的通話,RFC 3339 格式,如 2026-10-04T19:23:00Z |
end_time | String | 否 | 只返回發起時間早於它的通話,格式同上 |
limit | Number | 否 | 每頁條數,1 到 100,預設 20 |
cursor | String | 否 | 下一頁的遊標,即上一頁返回的 next_cursor,第一頁不傳 |
各條件可以組合使用。
請求示例
curl "$IM_API/$ORG/$APP/calls?username=alice&limit=2" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
items | Array<Object> | 本頁的通話,即不含 members 的通話物件 |
next_cursor | String | 下一頁的遊標。沒有下一頁時為空字串 "" |
{
"items": [
{
"call_id": "100313814330769408",
"type": "single",
"group_id": null,
"media": "audio",
"status": "ended",
"initiator": "bob",
"max_participants": 2,
"joined_count": 0,
"ext": null,
"created_at": "2026-10-04T19:31:17.077Z",
"answered_at": "2026-10-04T19:31:21.115Z",
"ended_at": "2026-10-04T19:31:49.168Z",
"end_reason": "completed",
"ended_by": "bob",
"duration_seconds": 28,
"version": 3,
"ended_via": "client",
"member_count": 2,
"peak_joined": 2,
"billable_minutes": 2
},
{
"call_id": "100313666666102784",
"type": "group",
"group_id": "100311544667045888",
"media": "video",
"status": "ended",
"initiator": "alice",
"max_participants": 16,
"joined_count": 0,
"ext": {
"topic": "周会"
},
"created_at": "2026-10-04T19:30:41.871Z",
"answered_at": "2026-10-04T19:30:44.923Z",
"ended_at": "2026-10-04T19:31:17.049Z",
"end_reason": "completed",
"ended_by": "alice",
"duration_seconds": 32,
"version": 5,
"ended_via": "client",
"member_count": 3,
"peak_joined": 3,
"billable_minutes": 3
}
],
"next_cursor": "100313666666102784"
}以 next_cursor 判斷是否還有下一頁
一次請求最多檢查 1000 個通話。條件很少命中時(如按 type 篩選、或同時按 status 和 username 篩選),一頁可能不足 limit 條,甚至為空,但 next_cursor 不為空,請繼續用它翻頁,直到 next_cursor 為空字串。不要以本頁的條數判斷是否已經查完。
錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | 引數不正確,details.field 指出是哪個引數:type 不是 single 或 group,status 不是 ringing、active 或 ended,start_time、end_time 不是 RFC 3339 格式,group_id 不是群 ID,limit 不在 1 到 100 之間,cursor 不正確 |
查詢通話詳情
按通話 ID 查詢一個通話,包括全部成員。通話 ID 可以從通話列表、會話中的通話記錄訊息或事件回撥中取得。
/{org_name}/{app_name}/calls/{call_id}路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
call_id | String | 通話 ID |
請求示例
curl "$IM_API/$ORG/$APP/calls/100313814330769408" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK,響應體為通話物件。一個已結束的一對一語音通話:
{
"call_id": "100313814330769408",
"type": "single",
"group_id": null,
"media": "audio",
"status": "ended",
"initiator": "bob",
"max_participants": 2,
"joined_count": 0,
"ext": null,
"created_at": "2026-10-04T19:31:17.077Z",
"answered_at": "2026-10-04T19:31:21.115Z",
"ended_at": "2026-10-04T19:31:49.168Z",
"end_reason": "completed",
"ended_by": "bob",
"duration_seconds": 28,
"version": 3,
"members": [
{
"username": "bob",
"role": "initiator",
"state": "left",
"media_uid": 1,
"invited_by": null,
"ring_expires_at": null,
"joined_at": "2026-10-04T19:31:17.077Z",
"left_at": "2026-10-04T19:31:49.168Z",
"leave_reason": "hangup",
"invited_at": null,
"joined_platform": "android",
"join_count": 1,
"joined_ms": 28053,
"first_joined_at": "2026-10-04T19:31:17.077Z",
"media_joined_at": "2026-10-04T19:31:17.094Z",
"media_left_at": null
},
{
"username": "alice",
"role": "invitee",
"state": "left",
"media_uid": 2,
"invited_by": "bob",
"ring_expires_at": "2026-10-04T19:32:17.077Z",
"joined_at": "2026-10-04T19:31:21.115Z",
"left_at": "2026-10-04T19:31:49.168Z",
"leave_reason": "ended",
"invited_at": "2026-10-04T19:31:17.077Z",
"joined_platform": "ios",
"join_count": 1,
"joined_ms": 28053,
"first_joined_at": "2026-10-04T19:31:21.115Z",
"media_joined_at": "2026-10-04T19:31:21.131Z",
"media_left_at": null
}
],
"ended_via": "client",
"member_count": 2,
"peak_joined": 2,
"billable_minutes": 2
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 404 | not_found | 通話不存在、不屬於本應用,或已超過 180 天的保留期 |
結束通話
強制結束一個進行中的通話,例如發現違規內容、業務上的服務時間已到。結束後:
- 在通話中的成員全部離開(
leave_reason為ended),正在振鈴的邀請取消,被叫裝置上的來電通知被替換為“未接來電”; - 通話的
end_reason為server_ended,ended_via為openapi,ended_by為null; - 成員的線上裝置收到通話結束的通知,媒體房間隨即關閉,仍連著的裝置被斷開;
- 與其他原因結束的通話一樣,會話中寫入通話記錄,併傳送
rtc.call_ended事件回撥。
通話已經結束的,返回 200 OK,changed 為 false,通話不變,可以放心重試。
/{org_name}/{app_name}/calls/{call_id}/end路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
call_id | String | 通話 ID |
請求體
請求體可以省略。
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
reason | String | 否 | 結束的原因,1 到 256 個字元,首尾的空白會被去掉。記入控制檯的操作日誌,不會告訴使用者 |
請求示例
curl -X POST "$IM_API/$ORG/$APP/calls/100311615936659456/end" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "会议已结束"
}'響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
call | Object | 結束後的通話物件 |
changed | Boolean | 是否結束了通話。通話之前已經結束的為 false |
一個群語音通話被結束,其中 dave 之前已被移出通話:
{
"call": {
"call_id": "100311615936659456",
"type": "group",
"group_id": "100311544667045888",
"media": "audio",
"status": "ended",
"initiator": "alice",
"max_participants": 16,
"joined_count": 0,
"ext": {
"topic": "周会"
},
"created_at": "2026-10-04T19:22:32.940Z",
"answered_at": "2026-10-04T19:22:33.988Z",
"ended_at": "2026-10-04T19:22:38.122Z",
"end_reason": "server_ended",
"ended_by": null,
"duration_seconds": 4,
"version": 6,
"members": [
{
"username": "alice",
"role": "initiator",
"state": "left",
"media_uid": 1,
"invited_by": null,
"ring_expires_at": null,
"joined_at": "2026-10-04T19:22:32.940Z",
"left_at": "2026-10-04T19:22:38.122Z",
"leave_reason": "ended",
"invited_at": null,
"joined_platform": "ios",
"join_count": 1,
"joined_ms": 4134,
"first_joined_at": "2026-10-04T19:22:32.940Z",
"media_joined_at": "2026-10-04T19:22:34.045Z",
"media_left_at": null
},
{
"username": "bob",
"role": "invitee",
"state": "left",
"media_uid": 2,
"invited_by": "alice",
"ring_expires_at": "2026-10-04T19:23:32.940Z",
"joined_at": "2026-10-04T19:22:33.988Z",
"left_at": "2026-10-04T19:22:38.122Z",
"leave_reason": "ended",
"invited_at": "2026-10-04T19:22:32.940Z",
"joined_platform": "android",
"join_count": 1,
"joined_ms": 4134,
"first_joined_at": "2026-10-04T19:22:33.988Z",
"media_joined_at": "2026-10-04T19:22:34.056Z",
"media_left_at": null
},
{
"username": "carol",
"role": "invitee",
"state": "declined",
"media_uid": 3,
"invited_by": "alice",
"ring_expires_at": "2026-10-04T19:23:32.940Z",
"joined_at": null,
"left_at": null,
"leave_reason": null,
"invited_at": "2026-10-04T19:22:32.940Z",
"joined_platform": null,
"join_count": 0,
"joined_ms": 0,
"first_joined_at": null,
"media_joined_at": null,
"media_left_at": null
},
{
"username": "dave",
"role": "joiner",
"state": "left",
"media_uid": 4,
"invited_by": null,
"ring_expires_at": null,
"joined_at": "2026-10-04T19:22:34.030Z",
"left_at": "2026-10-04T19:22:37.089Z",
"leave_reason": "removed",
"invited_at": null,
"joined_platform": "ios",
"join_count": 1,
"joined_ms": 3059,
"first_joined_at": "2026-10-04T19:22:34.030Z",
"media_joined_at": "2026-10-04T19:22:34.067Z",
"media_left_at": null
}
],
"ended_via": "openapi",
"member_count": 4,
"peak_joined": 3,
"billable_minutes": 3
},
"changed": true
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | reason 超過 256 個字元,details.field 為 reason |
| 404 | not_found | 通話不存在、不屬於本應用,或已超過 180 天的保留期 |
把成員移出通話
把一個成員移出通話,用於群通話中處置個別成員:
- 在通話中的成員:離開通話(
leave_reason為removed),同時被移出媒體房間,不能憑手中的媒體憑據繼續收聽; - 正在振鈴的成員:邀請被取消(
state為canceled),停止振鈴; - 其他成員收到成員變化的通知,被移出的人收到本人離開或邀請取消的通知;
- 移出後在通話中的人數降為 0 的,通話隨之結束:接透過的
end_reason為completed,沒有接透過的為canceled;只剩一人且沒有正在振鈴的邀請的,60 秒後結束,見群通話; - 一對一通話:移出任何一方都等同結束通話,
end_reason為server_ended。
被移出的成員只要仍能在群裡發言,就可以重新加入這個群通話。要阻止他再加入,請同時把他移出群或在群裡禁言他。
成員已不在通話中、也不在振鈴(如已經離開、拒絕),或者通話已經結束的,返回 200 OK,changed 為 false。
/{org_name}/{app_name}/calls/{call_id}/members/{username}/remove路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
call_id | String | 通話 ID |
username | String | 要移出的成員的使用者名稱 |
請求體
請求體可以省略。
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
reason | String | 否 | 移出的原因,1 到 256 個字元,首尾的空白會被去掉。記入控制檯的操作日誌,不會告訴使用者 |
請求示例
curl -X POST "$IM_API/$ORG/$APP/calls/100311615936659456/members/dave/remove" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "违规发言,移出通话"
}'響應
成功返回 200 OK,格式與結束通話相同:call 為移出後的通話物件,changed 表示是否有變化。
{
"call": {
"call_id": "100311615936659456",
"type": "group",
"group_id": "100311544667045888",
"media": "audio",
"status": "active",
"initiator": "alice",
"max_participants": 16,
"joined_count": 2,
"ext": {
"topic": "周会"
},
"created_at": "2026-10-04T19:22:32.940Z",
"answered_at": "2026-10-04T19:22:33.988Z",
"ended_at": null,
"end_reason": null,
"ended_by": null,
"duration_seconds": 3,
"version": 5,
"members": [
{
"username": "alice",
"role": "initiator",
"state": "joined",
"media_uid": 1,
"invited_by": null,
"ring_expires_at": null,
"joined_at": "2026-10-04T19:22:32.940Z",
"left_at": null,
"leave_reason": null,
"invited_at": null,
"joined_platform": "ios",
"join_count": 1,
"joined_ms": 0,
"first_joined_at": "2026-10-04T19:22:32.940Z",
"media_joined_at": "2026-10-04T19:22:34.045Z",
"media_left_at": null
},
{
"username": "bob",
"role": "invitee",
"state": "joined",
"media_uid": 2,
"invited_by": "alice",
"ring_expires_at": "2026-10-04T19:23:32.940Z",
"joined_at": "2026-10-04T19:22:33.988Z",
"left_at": null,
"leave_reason": null,
"invited_at": "2026-10-04T19:22:32.940Z",
"joined_platform": "android",
"join_count": 1,
"joined_ms": 0,
"first_joined_at": "2026-10-04T19:22:33.988Z",
"media_joined_at": "2026-10-04T19:22:34.056Z",
"media_left_at": null
},
{
"username": "carol",
"role": "invitee",
"state": "declined",
"media_uid": 3,
"invited_by": "alice",
"ring_expires_at": "2026-10-04T19:23:32.940Z",
"joined_at": null,
"left_at": null,
"leave_reason": null,
"invited_at": "2026-10-04T19:22:32.940Z",
"joined_platform": null,
"join_count": 0,
"joined_ms": 0,
"first_joined_at": null,
"media_joined_at": null,
"media_left_at": null
},
{
"username": "dave",
"role": "joiner",
"state": "left",
"media_uid": 4,
"invited_by": null,
"ring_expires_at": null,
"joined_at": "2026-10-04T19:22:34.030Z",
"left_at": "2026-10-04T19:22:37.089Z",
"leave_reason": "removed",
"invited_at": null,
"joined_platform": "ios",
"join_count": 1,
"joined_ms": 3059,
"first_joined_at": "2026-10-04T19:22:34.030Z",
"media_joined_at": "2026-10-04T19:22:34.067Z",
"media_left_at": null
}
],
"ended_via": null,
"member_count": 4,
"peak_joined": 3,
"billable_minutes": 0
},
"changed": true
}仍在通話中的成員(alice、bob)的 joined_ms 在他們離開時才累計,所以這裡為 0。
錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | reason 超過 256 個字元,details.field 為 reason |
| 404 | not_found | 通話不存在、不屬於本應用,或已超過 180 天的保留期(“通話不存在”);使用者不存在,或不是這個通話的成員(“使用者不存在”) |
查詢使用者正在進行的通話
查詢一個使用者此刻正在進行的通話和正在振鈴的來電,例如在客服系統中顯示坐席是否正在通話,或在發起業務操作前確認使用者不在通話中。
/{org_name}/{app_name}/users/{username}/calls/active路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱 |
請求示例
curl "$IM_API/$ORG/$APP/users/bob/calls/active" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
current | Object | 使用者正在進行的通話,即他在通話中、或他發起後正在等待對方接聽的通話,為包括成員的通話物件;不在通話中為 null |
incoming | Array<Object> | 使用者正在振鈴、還沒有超時的來電,最多 20 個,每項為包括成員的通話物件;沒有為空陣列 |
使用者正在收到一個一對一影片來電:
{
"current": null,
"incoming": [
{
"call_id": "100311142651396096",
"type": "single",
"group_id": null,
"media": "video",
"status": "ringing",
"initiator": "alice",
"max_participants": 2,
"joined_count": 1,
"ext": {
"order_id": "8812"
},
"created_at": "2026-10-04T19:20:40.099Z",
"answered_at": null,
"ended_at": null,
"end_reason": null,
"ended_by": null,
"duration_seconds": 0,
"version": 1,
"members": [
{
"username": "alice",
"role": "initiator",
"state": "joined",
"media_uid": 1,
"invited_by": null,
"ring_expires_at": null,
"joined_at": "2026-10-04T19:20:40.099Z",
"left_at": null,
"leave_reason": null,
"invited_at": null,
"joined_platform": "ios",
"join_count": 1,
"joined_ms": 0,
"first_joined_at": "2026-10-04T19:20:40.099Z",
"media_joined_at": null,
"media_left_at": null
},
{
"username": "bob",
"role": "invitee",
"state": "ringing",
"media_uid": 2,
"invited_by": "alice",
"ring_expires_at": "2026-10-04T19:21:40.099Z",
"joined_at": null,
"left_at": null,
"leave_reason": null,
"invited_at": "2026-10-04T19:20:40.099Z",
"joined_platform": null,
"join_count": 0,
"joined_ms": 0,
"first_joined_at": null,
"media_joined_at": null,
"media_left_at": null
}
],
"ended_via": null,
"member_count": 2,
"peak_joined": 1,
"billable_minutes": 0
}
]
}使用者既不在通話中、也沒有來電時:
{
"current": null,
"incoming": []
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 404 | not_found | 使用者不存在或已刪除 |
查詢通話統計
查詢本應用一段日期內每天的通話統計,與控制檯“音影片”頁面的統計相同。統計按北京時間劃分自然日,通話計入它結束的那一天;當天的資料隨通話結束隨時更新。
/{org_name}/{app_name}/rtc/stats路徑引數
org_name、app_name 見接入概述。
查詢引數
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
from | String | 是 | 開始日期,YYYY-MM-DD |
to | String | 是 | 結束日期,YYYY-MM-DD,包含這一天。不能早於 from,一次最多查詢 92 天 |
請求示例
curl "$IM_API/$ORG/$APP/rtc/stats?from=2026-10-01&to=2026-10-05" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK,items 為每天的統計,按日期升序。沒有通話的日期不在其中。
| 欄位 | 型別 | 說明 |
|---|---|---|
items[].date | String | 日期,YYYY-MM-DD |
items[].calls | Number | 當天結束的通話數,包括髮起時被叫忙線、立即結束的 |
items[].group_calls | Number | 其中的群通話數 |
items[].answered_calls | Number | 其中接透過的通話數。接通率為 answered_calls / calls |
items[].ended_completed | Number | 結束原因為 completed 的通話數 |
items[].ended_canceled | Number | 結束原因為 canceled 的通話數 |
items[].ended_rejected | Number | 結束原因為 rejected 的通話數 |
items[].ended_busy | Number | 結束原因為 busy 的通話數 |
items[].ended_no_answer | Number | 結束原因為 no_answer 的通話數 |
items[].ended_connection_lost | Number | 結束原因為 connection_lost 的通話數 |
items[].ended_other | Number | 其他結束原因的通話數,如 server_ended、user_unavailable、app_unavailable |
items[].duration_ms | Number | 接透過的通話的時長(從接通到結束)合計,毫秒 |
items[].audio_participant_ms | Number | 語音通話中各成員在通話中的時長合計,即成員的 joined_ms 之和,毫秒 |
items[].video_participant_ms | Number | 視訊通話中各成員在通話中的時長合計,毫秒 |
items[].billable_audio_minutes | Number | 語音通話的計費分鐘數合計 |
items[].billable_video_minutes | Number | 視訊通話的計費分鐘數合計 |
items[].answer_wait_ms | Number | 接透過的通話從發起到接通的等待時間合計,毫秒。平均接通等待為 answer_wait_ms / answered_calls |
items[].joined_members | Number | 接透過的通話中加入過通話的人次 |
items[].media_missing_members | Number | 其中一直沒有連上媒體服務的人次。佔 joined_members 的比例明顯偏高時,可能是部分使用者的網路無法連線媒體服務,請聯絡我們排查 |
items[].peak_concurrent_calls | Number | 當天同時進行的通話數的峰值,每分鐘取樣一次,很短的通話可能沒有采到 |
items[].peak_at | String | 峰值出現的時間,沒有采到為 null |
{
"items": [
{
"date": "2026-10-05",
"calls": 18,
"group_calls": 3,
"answered_calls": 10,
"ended_completed": 5,
"ended_canceled": 4,
"ended_rejected": 1,
"ended_busy": 2,
"ended_no_answer": 1,
"ended_connection_lost": 1,
"ended_other": 4,
"duration_ms": 117736,
"audio_participant_ms": 69425,
"video_participant_ms": 184133,
"billable_audio_minutes": 13,
"billable_video_minutes": 9,
"answer_wait_ms": 11317,
"joined_members": 22,
"media_missing_members": 12,
"peak_concurrent_calls": 2,
"peak_at": "2026-10-04T19:23:22.358Z"
}
]
}date 按北京時間劃分,peak_at 等時間是 UTC 時間,所以示例中 2026-10-05 的峰值時間顯示為 2026-10-04T19:23:22.358Z(北京時間 10 月 5 日 03:23)。
錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | details.reason 為 invalid_date_range:缺少 from 或 to、格式不是 YYYY-MM-DD、to 早於 from,或超過 92 天 |
獨立頻道介面
本頁只管理用 call_id 標識的通話。用 channel_id 標識的會議、語音房使用頻道管理、頻道會話與成員管理和頻道用量與更正;不要把頻道 ID 傳給本頁的介面。
統計與實際扣費的區別
響應中的 billable_minutes 和每天的語音、影片分鐘只是統計口徑,不是扣費的金額。新計費按媒體服務實際收到的檔位和本應用每月累計的標準時長扣餘額,不會按這些欄位再扣一次。對賬時分別核對通話的結束時間、統計計入的日期和音影片流水。
