查询与导出消息
本页的接口用于在服务端读取消息:按消息 ID 的顺序导出应用内的全部消息,用于归档和数据分析;按 ID 查询单条消息;查询某个用户发过的消息,用于处理投诉和刷屏。按会话查询历史消息(可以按时间段筛选)见会话与历史消息。
这些接口都以服务端的视角返回消息对象:
一次响应中的消息合计不超过 1 MB,超出时提前结束这一页,按翻页字段继续获取即可。
导出应用的消息
按消息 ID 从小到大导出应用内全部会话的消息,包括单聊、群聊消息和群提示。第一次调用不传 after_message_id,从最早的消息开始;之后每次传上一页返回的 next_after_message_id,直到 has_more 为 false。
GET
/{org_name}/{app_name}/messages- 只导出 30 秒之前的消息:为了保证按 ID 翻页不漏掉消息,只返回发送时间早于当前时间 30 秒的消息,刚发送的消息要稍后才能导出。
- 增量导出:
has_more为false表示已经导出到最新的可导出的消息。保存这一页的next_after_message_id,下次从它继续,就能只导出之后的新消息。 - 已撤回、已擦除的消息也会导出,但不含内容;之后才撤回或编辑的消息,已导出的内容不会自动更新。需要保存撤回前的原内容时,请在撤回前导出。
- 补齐消息抄送:用事件回调的
message.sent接收消息抄送时,回调地址暂停、停用或积压期间可能有消息没有抄送,可以用本接口从缺口之前的某个消息 ID 开始导出补齐,按message_id去重,见用好消息抄送。
路径参数
org_name、app_name 见接入概述。
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
after_message_id | String | 否 | 从这个消息 ID 之后开始导出(不含它本身),传上一页的 next_after_message_id。不传时从最早的消息开始 |
limit | Number | 否 | 每页条数,默认 100,取值 1 到 1000 |
请求示例
bash
curl "$IM_API/$ORG/$APP/messages?after_message_id=99582642738954240&limit=2" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK:
| 字段 | 类型 | 说明 |
|---|---|---|
items | Array<Object> | 本页的消息对象,按消息 ID 从小到大排列 |
next_after_message_id | String | 下一页的起点,传给下一次请求的 after_message_id。本页没有消息时与请求中的 after_message_id 相同 |
has_more | Boolean | 是否可能还有下一页。为 true 时请继续请求,下一页可能为空 |
json
{
"items": [
{
"conversation_id": "99582604130385920",
"conversation_type": "single",
"seq": 7,
"message_id": "99582642919309312",
"client_msg_id": "2ec322dc5f952fd2d05bc6df94a44d9a",
"sender": "bob",
"sender_type": "user",
"recipient": "alice",
"type": "custom",
"body": { "card": "order_shipped", "order_id": "8812", "status": "delivered" },
"ext": null,
"mentions": null,
"reply_to": null,
"need_receipt": false,
"exclude_from_unread": false,
"reactions": null,
"pinned": null,
"edited": { "at": "2026-10-02T19:08:27.418Z", "count": 2 },
"recalled": null,
"erased": false,
"via": "openapi",
"created_at": "2026-10-02T19:05:52.228Z",
"message_version": 2
},
{
"conversation_id": "99582580415791104",
"conversation_type": "group",
"seq": 3,
"message_id": "99582672556261376",
"client_msg_id": "doc-grp-0001",
"sender": "alice",
"sender_type": "user",
"recipient": null,
"type": "text",
"body": { "text": "@bob 请看一下需求文档" },
"ext": null,
"mentions": { "usernames": ["bob"], "all": false },
"reply_to": null,
"need_receipt": false,
"exclude_from_unread": false,
"reactions": null,
"pinned": { "by": null, "at": "2026-10-02T19:08:36.382Z" },
"edited": null,
"recalled": null,
"erased": false,
"via": "openapi",
"created_at": "2026-10-02T19:05:59.294Z",
"message_version": 1
}
],
"next_after_message_id": "99582672556261376",
"has_more": true
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | after_message_id 不是非负整数,或 limit 不在 1 到 1000 之间 |
查询单条消息
按消息 ID 查询一条消息。
GET
/{org_name}/{app_name}/messages/{message_id}路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
message_id | String | 消息 ID |
请求示例
bash
curl "$IM_API/$ORG/$APP/messages/99584445836689408" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK,响应体为消息对象:
json
{
"conversation_id": "99582580415791104",
"conversation_type": "group",
"seq": 9,
"message_id": "99584445836689408",
"client_msg_id": "5f0c2a7e-91b4-4d2e-a0c3-6b1e8f2d4c19",
"sender": "bob",
"sender_type": "user",
"recipient": null,
"type": "text",
"body": { "text": "@carol 文档已更新,请确认" },
"ext": { "biz_id": "PRD-2041" },
"mentions": { "usernames": ["carol"], "all": false },
"reply_to": { "seq": 3, "sender": "alice" },
"need_receipt": false,
"exclude_from_unread": false,
"reactions": null,
"pinned": null,
"edited": null,
"recalled": null,
"erased": false,
"via": "openapi",
"created_at": "2026-10-02T19:13:02.076Z",
"message_version": 0
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 404 | not_found | 消息不存在、已超过保留期,或 message_id 的格式不对 |
查询用户发出的消息
按消息 ID 从大到小(从新到旧)列出某个用户发过的消息,包括他在客户端发送的和服务端以他的身份发送的、单聊和群聊的,可以按时间段筛选。用于处理投诉和刷屏:例如先查出某个用户在一段时间内发的消息,再批量撤回。
GET
/{org_name}/{app_name}/users/{username}/sent-messages按游标分页。一页的条数可能少于 limit(超过保留期的消息会被跳过),请以 next_cursor 是否为 null 判断是否还有下一页。翻页时请保持 start_time、end_time 不变。
路径参数
org_name、app_name 见接入概述。
| 参数 | 类型 | 说明 |
|---|---|---|
username | String | 发送者的用户名 |
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
start_time | String | 否 | 只返回发送时间不早于这个时间的消息,RFC 3339 格式,如 2026-10-02T00:00:00Z。带时区偏移时,+ 要编码为 %2B,如 2026-10-02T08:00:00%2B08:00 |
end_time | String | 否 | 只返回发送时间早于这个时间的消息(不含),格式同上 |
cursor | String | 否 | 下一页的游标,第一页不传 |
limit | Number | 否 | 每页条数,默认 20,取值 1 到 100 |
请求示例
bash
curl "$IM_API/$ORG/$APP/users/bob/sent-messages?start_time=2026-10-02T00:00:00Z&limit=2" \
-H "Authorization: Bearer $APP_TOKEN"响应
成功返回 200 OK,items 为消息对象的列表,next_cursor 为下一页的游标:
json
{
"items": [
{
"conversation_id": "99582580415791104",
"conversation_type": "group",
"seq": 9,
"message_id": "99584445836689408",
"client_msg_id": "5f0c2a7e-91b4-4d2e-a0c3-6b1e8f2d4c19",
"sender": "bob",
"sender_type": "user",
"recipient": null,
"type": "text",
"body": { "text": "@carol 文档已更新,请确认" },
"ext": { "biz_id": "PRD-2041" },
"mentions": { "usernames": ["carol"], "all": false },
"reply_to": { "seq": 3, "sender": "alice" },
"need_receipt": false,
"exclude_from_unread": false,
"reactions": null,
"pinned": null,
"edited": null,
"recalled": null,
"erased": false,
"via": "openapi",
"created_at": "2026-10-02T19:13:02.076Z",
"message_version": 0
},
{
"conversation_id": "99582580415791104",
"conversation_type": "group",
"seq": 7,
"message_id": "99582995840630784",
"client_msg_id": "97250496646553a053befca0da838392",
"sender": "bob",
"sender_type": "user",
"recipient": null,
"type": "text",
"body": { "text": "好的,我下午看" },
"ext": null,
"mentions": null,
"reply_to": null,
"need_receipt": false,
"exclude_from_unread": false,
"reactions": null,
"pinned": null,
"edited": null,
"recalled": null,
"erased": false,
"via": "openapi",
"created_at": "2026-10-02T19:07:16.371Z",
"message_version": 0
}
],
"next_cursor": "99582995840630784"
}错误
| HTTP 状态码 | code | 说明 |
|---|---|---|
| 400 | invalid_argument | start_time、end_time 不是 RFC 3339 格式,cursor 无效,或 limit 不在 1 到 100 之间 |
| 404 | not_found | 用户不存在或已被删除 |
