好友
從你的服務端管理使用者的好友。好友關係是雙向的:A 是 B 的好友,B 也一定是 A 的好友。
建立好友關係有兩種方式:
| 方式 | 經過誰 | 適合 |
|---|---|---|
| 使用者在客戶端傳送好友申請 | 按對方的加好友方式處理;開啟了加好友前回撥時先問你的服務端 | 社交類 App,使用者自己加好友 |
| 你的服務端呼叫本頁的新增好友 | 不經過申請,不檢查加好友方式和黑名單,不呼叫回撥,立即成為好友 | 業務中已有的關係(如同一團隊的同事)、從其他 IM 匯入好友 |
例如,讓 alice 和 bob 成為好友,alice 給 bob 的備註是“產品-Bob”:
curl -X PUT "$IM_API/$ORG/$APP/users/alice/friends/bob" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "remark": "产品-Bob" }'路徑中的 {username} 是關係的所有者,{friend} 是對方。備註和自定義屬性只屬於所有者這一側,對方看不到。
- 好友數上限:執行策略的
friend_limit(預設 3000,可設 1 到 100000,見執行策略)。成為好友時雙方都檢查,任一方滿了都不能加;調低上限不會刪除已有好友。 - 客戶端通知:所有者的線上裝置實時收到
friend.added、friend.updated、friend.removed。新增和刪除會改變雙方的列表,雙方都收到。 - 只能給好友發訊息:應用開啟
friend_check_enabled後,使用者在客戶端給非好友發單聊返回403 not_friend。 - 封禁和刪除:封禁不影響好友關係;使用者被刪除後好友關係自動解除,他的好友收到刪除通知。
好友列表的版本號
每個使用者的好友列表有一個版本號,列表內容每變化一次加 1。新增、修改、刪除單個好友的介面都返回 changed 和 friend_version:changed 為 true 表示這次請求改變了所有者的好友列表,friend_version 是改變後的版本號;為 false 表示沒有改變(如重複新增且內容相同、刪除本來就不存在的好友),friend_version 是當前的版本號。因此重複呼叫這些介面都返回 200 OK,可以放心重試。
應用只讀時
應用處於只讀狀態(如欠費只讀,見限流與應用狀態)時,新增好友和修改備註、自定義屬性返回 403 app_unavailable;查詢、刪除好友不受影響。
查詢好友列表
分頁返回使用者的好友列表,每頁預設 100 個、最多 500 個。列表按固定的順序返回(不按備註或暱稱排序),展示時請自行排序。
/{org_name}/{app_name}/users/{username}/friends路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱,不區分大小寫 |
查詢引數
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
limit | Number | 否 | 每頁條數,預設 100,取值 1 到 500 |
cursor | String | 否 | 下一頁的遊標,第一頁不傳,見分頁 |
known_version | Number | 否 | 你儲存的好友列表版本號,非負整數,只在請求第一頁時生效。與當前版本號相同時只返回列表頭(not_modified 為 true),不返回 items 和 next_cursor |
請求示例
curl "$IM_API/$ORG/$APP/users/alice/friends?limit=100" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
version | Number | 好友列表當前的版本號,從未有過好友的使用者為 0 |
not_modified | Boolean | 是否與請求中的 known_version 相同。為 true 時響應只有 version、not_modified、count、max_count 四個欄位 |
count | Number | 當前的好友數 |
max_count | Number | 好友數上限,即應用的 friend_limit |
items | Array<Object> | 本頁的好友,每項為好友物件 |
next_cursor | String | 下一頁的遊標,為 null 時沒有下一頁 |
{
"version": 2,
"not_modified": false,
"count": 2,
"max_count": 3000,
"items": [
{
"username": "bob",
"nickname": "鲍勃",
"avatar_url": "",
"remark": "老鲍",
"attributes": { "group": "同事", "star": "1" },
"add_source": "import",
"created_at": "2026-10-02T19:07:08.944Z"
},
{
"username": "carol",
"nickname": "卡罗尔",
"avatar_url": "",
"remark": "",
"attributes": null,
"add_source": "",
"created_at": "2026-10-02T19:07:08.989Z"
}
],
"next_cursor": null
}帶 known_version=2 且列表沒有變化時:
{
"version": 2,
"not_modified": true,
"count": 2,
"max_count": 3000
}- 分頁拉取過程中如果列表發生了變化,後面幾頁的
version會與第一頁不同。需要一份準確的完整列表時,發現version變化後從第一頁重新拉取。 - 已被刪除、但關係還在清理中的好友不會出現在列表中,這段時間裡一頁的條數可能少於
limit,count也可能暫時比實際返回的人數多。是否還有下一頁只看next_cursor。
錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | limit 不在 1 到 500 之間、known_version 不是非負整數,或 cursor 無效 |
| 404 | not_found | 使用者不存在或已刪除 |
檢查好友關係
批次檢查一個使用者與其他使用者的關係:是否好友、是否拉黑了對方、兩人之間是否有待處理的好友申請。常用於在業務頁面上顯示“加好友”“等待驗證”等狀態。
/{org_name}/{app_name}/users/{username}/friends/check路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱 |
請求體
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | Array<String> | 是 | 要檢查的使用者名稱,1 到 100 個 |
請求示例
curl -X POST "$IM_API/$ORG/$APP/users/alice/friends/check" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"usernames": ["bob", "erin", "frank", "Carol", "alice", "nobody"]
}'響應
成功返回 200 OK,items 按請求中的順序排列,使用者名稱轉為小寫後去重;不存在或已刪除的使用者、{username} 本人不出現在結果中。每一項為:
| 欄位 | 型別 | 說明 |
|---|---|---|
username | String | 對方的使用者名稱 |
is_friend | Boolean | 是否好友 |
blocked | Boolean | {username} 是否把對方加入了黑名單。不返回對方是否拉黑了 {username} |
request | String | 兩人之間未過期的待處理好友申請:sent 為 {username} 發出、對方尚未處理;received 為對方發來、{username} 尚未處理;沒有時為 null |
{
"items": [
{ "username": "bob", "is_friend": true, "blocked": false, "request": null },
{ "username": "erin", "is_friend": false, "blocked": false, "request": "received" },
{ "username": "frank", "is_friend": false, "blocked": false, "request": "sent" },
{ "username": "carol", "is_friend": true, "blocked": false, "request": null }
]
}這個介面是讀操作,無論檢查多少個使用者都只計一次呼叫。
錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | usernames 為空或超過 100 個 |
| 404 | not_found | {username} 不存在或已刪除 |
查詢單個好友
/{org_name}/{app_name}/users/{username}/friends/{friend}路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 關係的所有者 |
friend | String | 好友的使用者名稱 |
請求示例
curl "$IM_API/$ORG/$APP/users/alice/friends/bob" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK,響應體為好友物件。
{
"username": "bob",
"nickname": "鲍勃",
"avatar_url": "",
"remark": "老鲍",
"attributes": { "group": "同事", "star": "1" },
"add_source": "import",
"created_at": "2026-10-02T19:07:08.944Z"
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | {friend} 與 {username} 是同一個使用者 |
| 404 | not_found | 使用者不存在或已刪除(message 為“使用者不存在”),或兩人不是好友(message 為“對方不是你的好友”) |
新增好友
直接讓兩個使用者成為好友,不經過申請,不檢查雙方的加好友方式和黑名單,只檢查雙方的好友數上限。
- 只設定一側:
remark、attributes只寫{username}這一側,add_source雙方相同。 - 申請中預設的備註:沒傳
remark的一側,取他之前發給對方的待處理申請裡預設的備註,沒有就為空。兩人之間未過期的待處理申請改為“已成為好友”(accepted)。 - 已經是好友也算成功:把這次的
remark、attributes寫入{username}一側(沒傳的不變),add_source、created_at不變;有變化時changed為true。匯入時為雙方各呼叫一次,兩邊的備註都能寫進去。 - 通知:新成為好友時雙方線上裝置都收到;已經是好友、只改了備註或屬性時,只有
{username}收到。
/{org_name}/{app_name}/users/{username}/friends/{friend}路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 關係的所有者 |
friend | String | 要新增的好友的使用者名稱,不能是 {username} 本人 |
請求體
請求體可以省略。不能包含 username 欄位,對方取自路徑。
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
remark | String | 否 | {username} 給對方的備註,最長 64 個字元,不能包含控制字元,首尾空白自動去掉 |
attributes | Object | 否 | {username} 給對方設定的自定義屬性,字串鍵值對,規則見好友物件。已經是好友時按項合併,與修改好友相同 |
add_source | String | 否 | 新增來源,如 search、qrcode、group:1839201838123,最長 32 個字元,由字母、數字和 _、-、.、: 組成。雙方相同,成為好友後不能修改 |
created_at | String | 否 | 成為好友的時間,RFC 3339 格式,不能晚於當前時間。用於從其他 IM 匯入時保留原來的時間,預設為當前時間;已經是好友時忽略 |
請求示例
curl -X PUT "$IM_API/$ORG/$APP/users/alice/friends/bob" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"remark": "老鲍",
"attributes": { "star": "1", "group": "同事" },
"add_source": "import"
}'響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
friend | Object | {username} 一側的好友物件 |
changed | Boolean | 這次請求是否改變了 {username} 的好友列表 |
friend_version | Number | {username} 的好友列表版本號,見本頁開頭的說明 |
{
"friend": {
"username": "bob",
"nickname": "鲍勃",
"avatar_url": "",
"remark": "老鲍",
"attributes": { "group": "同事", "star": "1" },
"add_source": "import",
"created_at": "2026-10-02T19:07:08.944Z"
},
"changed": true,
"friend_version": 1
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | {friend} 是 {username} 本人;請求體包含 username;remark、attributes、add_source 不符合規則;created_at 晚於當前時間 |
| 404 | not_found | {username} 或 {friend} 不存在或已刪除 |
| 409 | limit_exceeded | 好友數已達上限。details.reason 為 friend_limit 時是 {username} 的好友數已滿,為 peer_friend_limit 時是對方的好友數已滿 |
{
"error": {
"code": "limit_exceeded",
"message": "对方的好友数已达上限",
"details": { "reason": "peer_friend_limit" },
"request_id": "QHDK7PQXPV3LFKEFLF37DST5RR"
}
}批次新增好友
為一個使用者一次新增最多 100 位好友,每一項的規則與新增好友相同。各項分別處理、互不影響,見批次介面。按項數計入應用的呼叫額度。
/{org_name}/{app_name}/users/{username}/friends/batch路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 關係的所有者 |
請求體
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
friends | Array<Object> | 是 | 要新增的好友,1 到 100 項 |
friends[].username | String | 是 | 好友的使用者名稱 |
friends[].remark | String | 否 | 同新增好友 |
friends[].attributes | Object | 否 | 同新增好友 |
friends[].add_source | String | 否 | 同新增好友 |
friends[].created_at | String | 否 | 同新增好友 |
請求示例
curl -X POST "$IM_API/$ORG/$APP/users/carol/friends/batch" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"friends": [
{ "username": "dave", "remark": "戴夫", "add_source": "import", "created_at": "2025-03-01T10:00:00Z" },
{ "username": "erin", "attributes": { "group": "同学" } },
{ "username": "alice" },
{ "username": "nobody" }
]
}'響應
成功返回 200 OK。同一個使用者名稱出現多次時不去重,按出現的次數逐個處理。
| 欄位 | 型別 | 說明 |
|---|---|---|
added | Array<Object> | 新增成功的項,每項為 {username} 一側的好友物件,包括原本就是好友的 |
failed | Array<Object> | 失敗的項,每項為 username(小寫)、code、message 和可選的 details,錯誤與新增好友相同 |
{
"added": [
{
"username": "dave",
"nickname": "戴夫",
"avatar_url": "",
"remark": "戴夫",
"attributes": null,
"add_source": "import",
"created_at": "2025-03-01T10:00:00.000Z"
},
{
"username": "erin",
"nickname": "艾琳",
"avatar_url": "",
"remark": "",
"attributes": { "group": "同学" },
"add_source": "",
"created_at": "2026-10-02T19:10:22.454Z"
},
{
"username": "alice",
"nickname": "爱丽丝",
"avatar_url": "",
"remark": "",
"attributes": null,
"add_source": "",
"created_at": "2026-10-02T19:07:08.989Z"
}
],
"failed": [
{ "username": "nobody", "code": "not_found", "message": "用户不存在" }
]
}批次介面不返回 changed 和版本號。
錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | friends 為空或超過 100 項 |
| 404 | not_found | {username} 不存在或已刪除 |
修改好友備註和自定義屬性
修改 {username} 給好友設定的備註和自定義屬性,隻影響 {username} 這一側。remark 和 attributes 至少傳一項,沒有傳的保持不變。內容有變化時 {username} 的線上裝置會收到修改的通知;與原值相同時 changed 為 false。
/{org_name}/{app_name}/users/{username}/friends/{friend}路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 關係的所有者 |
friend | String | 好友的使用者名稱 |
請求體
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
remark | String | 否 | 備註,最長 64 個字元,不能包含控制字元,首尾空白自動去掉;傳空字串表示清除 |
attributes | Object | 否 | 要修改的自定義屬性:只傳需要修改的項,值為 null 表示刪除這一項;整個欄位傳 null 表示清空全部。合併後的結果須符合好友物件中的規則 |
請求示例
把備註改為“鮑總”,刪除 star,新增 tag:
curl -X PATCH "$IM_API/$ORG/$APP/users/alice/friends/bob" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"remark": "鲍总",
"attributes": { "star": null, "tag": "vip" }
}'響應
成功返回 200 OK,欄位與新增好友的響應相同。
{
"friend": {
"username": "bob",
"nickname": "鲍勃",
"avatar_url": "",
"remark": "鲍总",
"attributes": { "group": "同事", "tag": "vip" },
"add_source": "import",
"created_at": "2026-10-02T19:07:08.944Z"
},
"changed": true,
"friend_version": 3
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | remark 和 attributes 都沒有傳;remark 或 attributes 不符合規則;{friend} 是 {username} 本人 |
| 404 | not_found | 使用者不存在或已刪除,或兩人不是好友 |
刪除好友
解除兩個使用者的好友關係,雙方同時解除,兩邊的備註和自定義屬性一併刪除。雙方的線上裝置都會收到刪除的通知,原因是“服務端刪除”,不會讓一方誤以為是對方刪除了自己。刪除好友不影響黑名單,也不影響兩人已有的會話和歷史訊息。
兩人本來就不是好友時同樣返回 200 OK,changed 為 false。
/{org_name}/{app_name}/users/{username}/friends/{friend}路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 關係的所有者 |
friend | String | 好友的使用者名稱 |
請求示例
curl -X DELETE "$IM_API/$ORG/$APP/users/carol/friends/erin" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
changed | Boolean | 是否確實刪除了好友關係 |
friend_version | Number | {username} 的好友列表版本號 |
{
"changed": true,
"friend_version": 4
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | {friend} 是 {username} 本人 |
| 404 | not_found | {username} 或 {friend} 不存在或已刪除 |
批次刪除好友
為一個使用者一次刪除最多 100 位好友,每一項的規則與刪除好友相同,本來就不是好友的也算刪除成功。按項數計入應用的呼叫額度。
/{org_name}/{app_name}/users/{username}/friends/batch-delete路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 關係的所有者 |
請求體
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
usernames | Array<String> | 是 | 要刪除的好友的使用者名稱,1 到 100 個 |
請求示例
curl -X POST "$IM_API/$ORG/$APP/users/carol/friends/batch-delete" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"usernames": ["dave", "bob", "nobody"]
}'響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
deleted | Array<String> | 刪除成功的使用者名稱,包括本來就不是好友的 |
failed | Array<Object> | 失敗的項,每項為 username(小寫)、code、message 和可選的 details,錯誤與刪除好友相同 |
{
"deleted": ["dave", "bob"],
"failed": [
{ "username": "nobody", "code": "not_found", "message": "用户不存在" }
]
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 400 | invalid_argument | usernames 為空或超過 100 個 |
| 404 | not_found | {username} 不存在或已刪除 |
刪除全部好友
刪除一個使用者的全部好友,用於員工離職時清空關係、回滾一次錯誤的匯入等場景。每次呼叫最多刪除 100 位,每位好友的規則與刪除好友相同。響應中 has_more 為 true 時請再次呼叫,直到為 false。
每次呼叫按這次取出的好友人數計入應用的呼叫額度(沒有好友時只計一次)。中途出錯時返回錯誤,已經刪除的不會恢復,再次呼叫即可繼續。
/{org_name}/{app_name}/users/{username}/friends路徑引數
org_name、app_name 見接入概述。
| 引數 | 型別 | 說明 |
|---|---|---|
username | String | 使用者名稱 |
請求示例
curl -X DELETE "$IM_API/$ORG/$APP/users/alice/friends" \
-H "Authorization: Bearer $APP_TOKEN"響應
成功返回 200 OK:
| 欄位 | 型別 | 說明 |
|---|---|---|
deleted_count | Number | 這次刪除的好友人數 |
has_more | Boolean | 是否還有沒刪除的好友 |
{
"deleted_count": 5,
"has_more": false
}錯誤
| HTTP 狀態碼 | code | 說明 |
|---|---|---|
| 404 | not_found | 使用者不存在或已刪除 |
資料結構
好友物件
所有者視角的一位好友。
| 欄位 | 型別 | 說明 |
|---|---|---|
username | String | 好友的使用者名稱 |
nickname | String | 好友的暱稱,沒有設定時為空字串 |
avatar_url | String | 好友的頭像地址,沒有設定時為空字串 |
remark | String | 所有者給好友設定的備註,沒有時為空字串 |
attributes | Object | 所有者給好友設定的自定義屬性,字串鍵值對,沒有時為 null |
add_source | String | 新增來源,沒有時為空字串 |
created_at | String | 成為好友的時間 |
{
"username": "bob",
"nickname": "鲍勃",
"avatar_url": "",
"remark": "老鲍",
"attributes": { "group": "同事", "star": "1" },
"add_source": "import",
"created_at": "2026-10-02T19:07:08.944Z"
}nickname、avatar_url取自好友當前的使用者資料。好友修改資料後,不會通知他的好友。- 備註:最長 64 個字元,不能包含控制字元。
- 自定義屬性:最多 16 項,JSON 編碼後合計不超過 1 KB;鍵為 1 到 32 個字元,由字母、數字和
_、-、.組成;值為字串。可以用它實現星標好友、好友分組等功能。 - 新增來源:記錄兩人是怎樣認識的,取值由你定義,如
search(搜尋)、qrcode(掃碼)、group:1839201838123(在某個群裡)。由使用者在客戶端傳送申請時提交的來源未經核實,只能用於展示和統計,不要作為許可權依據。成為好友後不能修改。
