推送设备与设置
你的服务端可以查看和修改用户的推送设置(全局免打扰、夜间免打扰、预览方式)和会话免打扰,例如与自己 App 中的“消息提醒”“勿扰模式”开关同步;还可以查看用户登记了推送的设备,在排查收不到推送、收到别人的推送这类问题时解绑其中一台。免打扰和预览方式的效果见离线推送。
- 与客户端共用一份设置:用户在客户端修改的也是同一份设置,双方的修改互相覆盖,以最后一次为准。
- 修改后通知用户的设备:推送设置或会话免打扰有变化时,用户全部在线的设备收到
push.settings_changed通知,客户端据此更新本地的设置。没有变化的修改(changed为false)不通知。 - 版本号:推送设置和会话免打扰共用一个版本号
settings_version,任何一项有变化都加一,客户端用它判断本地的设置是否最新。 - 用户的状态:用户不存在或已删除时,各接口返回
404 not_found;删除用户时,他的推送设置、会话免打扰和推送设备一并删除。被封禁的用户的设置保留,但他的推送设备随登录一起失效。 - 本页的接口只计入应用的 OpenAPI 调用额度,应用处于只读状态时都可以调用。
查询推送设置
/{org_name}/{app_name}/users/{username}/push-settings路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
请求示例
curl "$IM_API/$ORG/$APP/users/zhangsan/push-settings" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK,响应体为推送设置对象。用户从未设置过时:
{
"dnd": null,
"quiet_hours": null,
"preview": null,
"effective_preview": "full",
"settings_version": 0
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 404 | not_found | 用户不存在或已删除 |
修改推送设置
修改用户的全局免打扰、夜间免打扰和预览方式,只给出要修改的字段,没有给出的保持不变。
- 设置与当前相同时不算修改,
changed为false,版本号不变。全局免打扰以相同的时长再开启一次(到期时间相差不超过 1 分钟),同样不算修改,到期时间不变。 - 全局免打扰的时长从本次调用时开始计算,到期后自动关闭,用户的设备不会另外收到通知。
/{org_name}/{app_name}/users/{username}/push-settings路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
dnd | Object | 否 | 全局免打扰。null 关闭;{ "duration_seconds": 28800 } 开启一段时间,时长为 1 到 315360000 秒(10 年);{ "duration_seconds": null } 或 {} 一直开启 |
quiet_hours | Object | 否 | 夜间免打扰。null 关闭;或者为 start、end、timezone 三项,都必填:start、end 为开始和结束的时刻,格式为 HH:MM(24 小时制,两位数,如 07:30),两者不能相同,end 早于 start 表示跨过午夜;timezone 为 IANA 时区名称,如 Asia/Shanghai,不接受 GMT+8 这类写法 |
preview | String | 否 | 预览方式:full 显示发送者和内容,sender_only 只显示发送者,none 都不显示;null 清除用户的选择,改用应用运行策略的 push_default_preview |
请求示例
开启 8 小时的全局免打扰,设置每天 22:00 到次日 07:30 的夜间免打扰,通知只显示发送者:
curl -X PATCH "$IM_API/$ORG/$APP/users/zhangsan/push-settings" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"dnd": { "duration_seconds": 28800 },
"quiet_hours": { "start": "22:00", "end": "07:30", "timezone": "Asia/Shanghai" },
"preview": "sender_only"
}'响应
成功返回 200 OK,响应体为修改后的推送设置对象,另加 changed 字段,表示这次是否有变化。
{
"dnd": { "until": "2026-10-05T03:20:47.124Z" },
"quiet_hours": { "start": "22:00", "end": "07:30", "timezone": "Asia/Shanghai" },
"preview": "sender_only",
"effective_preview": "sender_only",
"settings_version": 1,
"changed": true
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | details.reason 为 invalid_duration:时长不在 1 到 315360000 秒之间;invalid_quiet_hours:时刻的格式不对,或开始等于结束;invalid_timezone:时区不是 IANA 时区名称;invalid_preview:预览方式不是 full、sender_only、none。请求体中有不认识的字段,或 dnd 不是对象也不是 null 时,没有 details.reason,details.field 指出字段 |
| 404 | not_found | 用户不存在或已删除 |
查询会话免打扰
查询用户设置了免打扰的单聊和群。已经到期的、单聊对方已删除的不返回,所以一页的条数可能少于 limit,是否还有下一页只看 next_cursor。
/{org_name}/{app_name}/users/{username}/push-settings/conversations路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
limit | Number | 否 | 每页条数,1 到 500,默认 100 |
cursor | String | 否 | 下一页的游标,取自上一页的 next_cursor,第一页不传 |
known_version | Number | 否 | 只用于第一页:你保存的 settings_version。与当前的版本号相同时,只返回 not_modified 为 true 和版本号,items 为空数组 |
请求示例
curl "$IM_API/$ORG/$APP/users/zhangsan/push-settings/conversations?limit=100" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK:
| 字段 | 类型 | 说明 |
|---|---|---|
settings_version | Number | 当前的版本号,从未设置过为 0 |
not_modified | Boolean | 第一页带的 known_version 与当前版本号相同时为 true |
items | Array<Object> | 会话免打扰,每项为会话免打扰对象,按会话类型(group 在前)和会话排序 |
next_cursor | String | 下一页的游标,没有下一页时为空字符串 |
{
"settings_version": 4,
"not_modified": false,
"items": [
{
"conversation_type": "group",
"target": "100311272729346048",
"mode": "mention_only",
"until": null,
"updated_at": "2026-10-04T19:21:19.963Z"
},
{
"conversation_type": "single",
"target": "lisi",
"mode": "none",
"until": "2026-10-05T19:21:20.019Z",
"updated_at": "2026-10-04T19:21:20.022Z"
}
],
"next_cursor": ""
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | limit 不在 1 到 500 之间,known_version 不是非负整数,或 cursor 无效 |
| 404 | not_found | 用户不存在或已删除 |
设置会话免打扰
为用户设置一个单聊或一个群的免打扰,已有设置的覆盖为本次的方式和时长。以相同的方式和时长再设置一次(到期时间相差不超过 1 分钟,或都一直有效),changed 为 false,到期时间不变。
设置群免打扰时用户必须是群成员。用户退出或被移出群后,这个群的免打扰随之删除,重新入群时从正常推送开始。
/{org_name}/{app_name}/users/{username}/push-settings/conversations/single/{peer}/{org_name}/{app_name}/users/{username}/push-settings/conversations/group/{group_id}路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
peer | String | 单聊的对方用户名,不能是用户本人 |
group_id | String | 群 ID |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
mode | String | 是 | 免打扰方式:none 不推送这个会话的消息;mention_only 只在有人 @ 本人时推送,只能用于群 |
duration_seconds | Number | 否 | 时长,单位为秒,1 到 315360000(10 年),从本次调用时开始计算,到期后自动恢复正常推送。省略或为 null 表示一直有效 |
请求示例
群里只在有人 @ 本人时推送:
curl -X PUT "$IM_API/$ORG/$APP/users/zhangsan/push-settings/conversations/group/100311272729346048" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "mention_only"
}'与 lisi 的单聊 1 天内不推送:
curl -X PUT "$IM_API/$ORG/$APP/users/zhangsan/push-settings/conversations/single/lisi" \
-H "Authorization: Bearer $APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "none",
"duration_seconds": 86400
}'响应
成功返回 200 OK,响应体为设置后的会话免打扰对象,另加 changed(这次是否有变化)和 settings_version(设置后的版本号)。
{
"conversation_type": "single",
"target": "lisi",
"mode": "none",
"until": "2026-10-05T19:21:20.019Z",
"updated_at": "2026-10-04T19:21:20.022Z",
"changed": true,
"settings_version": 4
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | details.reason 为 invalid_mode:mode 缺失或取值不对,或单聊设置了 mention_only;invalid_duration:时长不在 1 到 315360000 秒之间;self_conversation:单聊的对方是用户本人 |
| 403 | not_group_member | 用户不是这个群的成员,或群已解散 |
| 404 | not_found | 用户或单聊的对方不存在或已删除;群不存在 |
| 409 | limit_exceeded | details.reason 为 conversation_setting_limit:用户的会话免打扰已有 10000 个 |
取消会话免打扰
取消用户对一个单聊或一个群的免打扰,恢复正常推送。没有设置过(或已经到期)时同样返回成功,changed 为 false,可以放心重试。取消群免打扰时不检查成员身份,群不存在或用户已经不在群中也可以调用。
/{org_name}/{app_name}/users/{username}/push-settings/conversations/single/{peer}/{org_name}/{app_name}/users/{username}/push-settings/conversations/group/{group_id}路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
peer | String | 单聊的对方用户名 |
group_id | String | 群 ID |
请求示例
curl -X DELETE "$IM_API/$ORG/$APP/users/zhangsan/push-settings/conversations/single/lisi" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK:
| 字段 | 类型 | 说明 |
|---|---|---|
changed | Boolean | 这次是否取消了一项有效的设置 |
settings_version | Number | 取消后的版本号 |
{
"changed": true,
"settings_version": 5
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | details.reason 为 self_conversation:单聊的对方是用户本人 |
| 404 | not_found | 用户或单聊的对方不存在或已删除 |
查询推送设备
查询用户登记了推送的设备和令牌,按 session_id 升序排列。每台设备对应用户的一次登录,与查询登录设备返回的 session_id 相同;登录了但没有登记推送的设备(包括 Web 等不能登记的平台、用户关闭了通知的设备)不在其中。设备数受登录设备数的上限约束,结果不分页。
/{org_name}/{app_name}/users/{username}/push-devices路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
请求示例
curl "$IM_API/$ORG/$APP/users/zhangsan/push-devices" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK。items 为登记了推送的设备,每项为推送设备对象;没有时为空数组。
{
"items": [
{
"session_id": "100310865395318784",
"device_id": "5f0c2a9e-7d1b-4c7e-9a51-2f6d0f3b8c11",
"platform": "ios",
"language": "zh-Hans-CN",
"tokens": [
{ "kind": "alert", "priority": 1, "credential": "ios-prod", "channel": "apns", "token": "6abf38…f665" },
{ "kind": "voip", "priority": 1, "credential": "ios-prod", "channel": "apns", "token": "13b7b7…32c0" }
],
"badge": 6,
"login_at": "2026-10-04T19:19:33.998Z",
"updated_at": "2026-10-04T19:19:48.452Z"
},
{
"session_id": "100310865730863104",
"device_id": "a3d91c07-58e2-4f6b-b1c4-7e0f2d9a6c35",
"platform": "android",
"language": "zh-CN",
"tokens": [
{ "kind": "alert", "priority": 1, "credential": "xiaomi-main", "channel": "xiaomi", "token": "Lx9Qw2…Kd3P" },
{ "kind": "alert", "priority": 2, "credential": "fcm-global", "channel": "fcm", "token": "cR5tY8…nM0q" }
],
"badge": 0,
"login_at": "2026-10-04T19:19:34.079Z",
"updated_at": "2026-10-04T19:27:20.056Z"
}
]
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 404 | not_found | 用户不存在或已删除 |
解绑推送设备
删除用户一台设备的推送登记,这台设备随即收不到这个用户的离线推送。
- 只解绑推送,不影响登录:设备不会下线,App 下次启动或重新登记时又会恢复推送。要让设备彻底不再收到推送,请踢掉这台设备,或封禁用户。
- 设备没有登记推送(包括已经解绑过)时返回
404 not_found,重试时可以把它当作成功。 - 用户的设备不会收到解绑的通知。
/{org_name}/{app_name}/users/{username}/push-devices/{session_id}路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 用户名 |
session_id | String | 设备的会话 ID,取自查询推送设备的 session_id |
请求示例
curl -X DELETE "$IM_API/$ORG/$APP/users/zhangsan/push-devices/100310865730863104" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 204 No Content,没有响应体。
错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 404 | not_found | 用户不存在或已删除;这台设备没有登记推送、已经解绑,或者不属于这个用户 |
数据结构
推送设置对象
| 字段 | 类型 | 说明 |
|---|---|---|
dnd | Object | 全局免打扰,没有开启或已经到期时为 null。until 为到期时间,为 null 表示一直开启 |
quiet_hours | Object | 夜间免打扰,没有设置时为 null。start、end 为开始和结束的时刻(HH:MM,24 小时制),end 早于 start 表示跨过午夜,开始时刻算在时段内、结束时刻不算;timezone 为计算时段使用的 IANA 时区名称 |
preview | String | 用户选择的预览方式:full、sender_only、none。没有选择时为 null |
effective_preview | String | 实际生效的预览方式:用户选择过的取用户的选择,否则取应用运行策略的 push_default_preview |
settings_version | Number | 推送设置和会话免打扰共用的版本号,任何一项有变化都加一;从未设置过为 0 |
{
"dnd": { "until": null },
"quiet_hours": { "start": "22:00", "end": "07:30", "timezone": "Asia/Shanghai" },
"preview": "sender_only",
"effective_preview": "sender_only",
"settings_version": 2
}会话免打扰对象
| 字段 | 类型 | 说明 |
|---|---|---|
conversation_type | String | 会话类型:single 单聊,group 群聊 |
target | String | 单聊为对方的用户名,群聊为群 ID |
mode | String | 免打扰方式:none 不推送;mention_only 只在有人 @ 本人时推送(只用于群) |
until | String | 到期时间,为 null 表示一直有效 |
updated_at | String | 最近一次设置的时间 |
{
"conversation_type": "group",
"target": "100311272729346048",
"mode": "mention_only",
"until": null,
"updated_at": "2026-10-04T19:21:19.963Z"
}推送设备对象
| 字段 | 类型 | 说明 |
|---|---|---|
session_id | String | 设备的会话 ID,与登录设备对象的 session_id 相同 |
device_id | String | 设备标识,登录时由客户端提交 |
platform | String | 设备平台:ios、macos、android 或 harmony |
language | String | 设备登记的语言(BCP 47),通知按它选择模板的语言;没有登记时为 null,使用应用运行策略的 push_default_language |
tokens | Array<Object> | 设备的推送令牌,普通令牌按优先顺序在前,VoIP 令牌在后,每项的字段见下表 |
badge | Number | 这台设备当前的角标计数:App 最近一次上报的值,加上之后推送的条数 |
login_at | String | 这次登录的时间 |
updated_at | String | 推送登记最近一次更新的时间,App 每次登记都会更新 |
tokens 中每项的字段:
| 字段 | 类型 | 说明 |
|---|---|---|
kind | String | alert 普通令牌;voip VoIP 令牌,只用于 iOS 的来电 |
priority | Number | 普通令牌的优先顺序,从 1 开始,发送时先用小的;VoIP 令牌为 1 |
credential | String | 令牌所属的凭据名称。凭据已删除、令牌还没有清理时为空字符串 |
channel | String | 推送通道:apns、fcm、huawei、harmony、xiaomi、oppo、vivo、honor、meizu |
token | String | 遮盖后的令牌:只显示前 6 位和后 4 位,中间为 … |
{
"session_id": "100310865730863104",
"device_id": "a3d91c07-58e2-4f6b-b1c4-7e0f2d9a6c35",
"platform": "android",
"language": "zh-CN",
"tokens": [
{ "kind": "alert", "priority": 1, "credential": "xiaomi-main", "channel": "xiaomi", "token": "Lx9Qw2…Kd3P" },
{ "kind": "alert", "priority": 2, "credential": "fcm-global", "channel": "fcm", "token": "cR5tY8…nM0q" }
],
"badge": 0,
"login_at": "2026-10-04T19:19:34.079Z",
"updated_at": "2026-10-04T19:27:20.056Z"
}