SDK API 接口文档
用途
本文档说明 wx-bot-encry 对外暴露的 SDK 侧 HTTP API,用于外部系统和本地工具接入。
典型调用方:
agent-console- 本地管理工具
- 内部 webhook worker
- 可信的本地自动化脚本
注意:这是 SDK 侧接口,不是 agent-console 的代理接口。
基础地址
默认本地地址:
http://127.0.0.1:5080
常见默认值:
- host:
127.0.0.1 - port:
5080 - content type:
application/json
注意事项
- 本接口面向可信本地集成设计。
- 当前 SDK API 自身不强制 bearer-token 鉴权。
- 已为本地工具启用 CORS。
- SSE 接口是长连接。
- 队列和事件负载中的大部分时间戳为 Unix 秒。
- 群聊
session_id通常以@chatroom结尾。
健康检查与运行状态
GET /ping
简单存活探测。
响应示例:
pong
GET /status
返回 SDK 运行状态、授权状态、能力列表以及当前解析后的配置摘要。
响应示例:
{
"status": "running",
"auth_active": true,
"capabilities": ["fetch_messages", "dispatch_messages"],
"paused": {
"ingest_paused": false,
"send_paused": false
},
"config": {
"auth_server": "https://auth.example.com",
"api_endpoint": "http://127.0.0.1:5080",
"wechat_data_dir": "C:\\Users\\...\\xwechat_files\\xxx",
"decrypted_dir": "C:\\...\\data\\decrypted",
"self_wxid": "wxid_xxx",
"my_names": ["bot"],
"group_require_at_me": false,
"group_capture_mode": "all_group_messages"
},
"queue": {
"max_inbound_id": 120,
"max_event_id": 8,
"max_stream_id": 188,
"outbound_stats": {
"pending": 3,
"sent": 42
}
}
}
队列字段说明:
max_inbound_id: 旧版入站消息队列的最新游标max_event_id: 旧版类型事件队列的最新游标max_stream_id: 统一/stream事件流的最新游标
POST /control/pause
暂停或恢复 SDK worker。
请求体:
{
"ingest": true,
"send": false
}
字段说明:
ingest: 可选布尔值,控制消息采集 workersend: 可选布尔值,控制发送 worker
GET /control/status
返回当前暂停状态。
消息进入
GET /messages
从 SDK 本地队列拉取入站消息。
查询参数:
cursor: 整数,默认0limit: 整数,默认100,最大500
请求示例:
curl "http://127.0.0.1:5080/messages?cursor=0&limit=100"
响应示例:
{
"messages": [
{
"id": 101,
"msg_svr_id": "1234567890",
"session_id": "123456@chatroom",
"session_name": "测试群",
"sender_wxid": "wxid_xxx",
"sender_name": "张三",
"msg_text": "你好",
"msg_type": "text",
"image_path": null,
"recv_ts": 1776681000,
"mentioned_me": true,
"at_wxids": ["zhx870255124"],
"mention_mode": "metadata",
"is_self_sent": false,
"created_ts": 1776681001
}
],
"cursor": 101,
"count": 1
}
@ 提及相关字段:
mentioned_me: SDK 判断当前账号是否被提及at_wxids: 从微信msgsource.atuserlist中解析出的被 @ 目标mention_mode:metadata或空字符串is_self_sent: 该消息是否由当前登录微信账号发出
当前 SDK 行为:
- 群消息优先使用微信数据库元数据
source -> <atuserlist>判断 @。 - 如果没有 @ 元数据,则返回
mentioned_me=false。 - 私聊消息始终返回
mentioned_me=false。 - 自己发送的消息也会进入队列,便于审计和回放;消费方应使用
is_self_sent避免回复循环。
GET /messages/stream
入站消息 SSE 流。
兼容说明:
- 这是旧版兼容接口。
- 新接入建议使用
GET /stream。 /messages/stream只推送入站消息,不包含成员、授权、运行时等事件。
查询参数:
cursor: 整数,默认0heartbeat: 心跳秒数,默认15,范围5-60
请求示例:
curl -N "http://127.0.0.1:5080/messages/stream?cursor=0"
消息帧格式:
data: {"id":101,"session_id":"123456@chatroom",...}
心跳格式:
: heartbeat 1776681001
统一事件流
GET /stream
SDK 侧统一 SSE 事件流。
这是新接入的主要订阅接口。它把旧的消息流和事件流合并为一个游标空间、一条 SSE 连接。
当前事件类型包括:
message.receivedmessage.media.readygroup.member.joinedgroup.member.leftmessage.delivery.succeededmessage.delivery.failedauth.revokedruntime.warning
查询参数:
cursor: 整数,默认0heartbeat: 心跳秒数,默认15,范围5-60event_type: 可选,精确事件类型过滤session_id: 可选,会话过滤
请求示例:
curl -N "http://127.0.0.1:5080/stream?cursor=0"
消息帧格式:
id: 123
event: message.received
data: {"id":123,"event_id":"stream:123","event_type":"message.received",...}
心跳格式:
: heartbeat 1776681001
消费方约定:
- 持久化最后处理成功的整数
id。 - 重连时带上
cursor=<last_id>。 - 将
id视为 SDK 侧权威回放游标。 /messages和/events仅作为旧版拉取兼容接口保留。
message.media.ready 是图片消息的补充更新事件。图片消息首次进入队列时本地文件可能还未解析完成,稍后解析成功后会再次发出该事件。消费方应把它合并到原始图片消息上,而不是当作新的用户聊天轮次。
示例:
{
"event_type": "message.media.ready",
"message": {
"id": "1234567890",
"type": "image",
"text": "[图片]",
"image_path": "images/abc.png",
"recv_ts": 1777000000
},
"media": {
"type": "image",
"image_path": "images/abc.png",
"ready_ts": 1777000012
}
}
消息发送
POST /send
向本地发送队列写入一条出站消息。
文本消息示例:
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"sender_name": "客服",
"mention_sender": false,
"msg_type": "text",
"text": "你好,这是一条测试消息"
}
图片消息示例:
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"sender_name": "客服",
"mention_sender": false,
"msg_type": "image",
"image_url": "http://192.168.3.10:8000/plugins/draw/files/demo.png"
}
成功响应:
{
"queued": true,
"id": 88
}
校验规则:
session_id必填。- 文本消息需要
text或reply_text。 - 图片消息需要
image_path或image_url。 mention_sender可选,仅对群聊有意义。- 如果
mention_sender=true,SDK 发送 worker 会在最终文本前拼接@sender_name。
可选上下文字段:
sender_wxid: 原始发送人 wxidreply_to_msg_svr_id: 该回复对应的上游消息 idsession_kind:group或privateimage_url: 跨机器投递图片时使用的远程图片 URLsource_message: 原始入站消息快照对象delivery: 投递调试和审计元数据idempotency_key/command_id: 可选稳定出站命令键
这些额外字段会写入 SDK 出站队列,并可通过 GET /queue/messages 再次读取。文本消息中,如果 source_message 带有明确引用信息,例如 is_quote、refermsg 或 quote_text,当前 SDK 会在实际发送到微信时附加轻量引用预览。图片消息中,如果只提供了 image_url,SDK 会先下载到本地缓存目录,再调用微信桌面发送逻辑。
如果顶层或 delivery 内提供了 idempotency_key、command_id 或 outbound_idempotency_key,重复请求会返回既有出站队列行 id,而不会创建新的发送任务。没有显式幂等键的普通消息保持历史追加队列行为。
POST /send/batch
一次请求写入多条出站消息。
请求示例:
{
"messages": [
{
"session_id": "wxid_xxx",
"session_name": "李四",
"sender_name": "客服",
"mention_sender": false,
"msg_type": "text",
"text": "第一条"
},
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"sender_name": "客服",
"mention_sender": true,
"msg_type": "text",
"text": "第二条"
}
]
}
POST /send/envelope
写入一条结构化出站 envelope,适合第三方系统集成。
该接口提供比旧版扁平 /send 更完整的协议结构,但内部仍写入同一张 SDK 出站队列表。对于文本消息,如果 source_message 包含引用元数据,实际发送时可能会渲染轻量引用后缀。
请求示例:
{
"target": {
"session_id": "123456@chatroom",
"session_name": "测试群",
"session_kind": "group"
},
"sender": {
"wxid": "wxid_customer",
"name": "张三"
},
"content": {
"msg_type": "image",
"image_url": "http://192.168.3.10:8000/plugins/draw/files/demo.png"
},
"reply": {
"mention_sender": true,
"reply_to_msg_svr_id": "1234567890"
},
"source_message": {
"message_id": "1234567890",
"sender_wxid": "wxid_customer"
},
"delivery": {
"channel": "wechat",
"command_id": "wxbot-reply-12345",
"provider": "third-party-bridge"
},
"metadata": {
"trace_id": "trace-demo"
}
}
校验规则:
target.session_id必填。content.msg_type必须是text或image。- 文本 envelope 需要
content.text。 - 图片 envelope 需要
content.image_path或content.image_url。 target.session_kind如提供,必须是group或private。
成功响应:
{
"queued": true,
"id": 99,
"protocol": "envelope",
"normalized": {
"session_id": "123456@chatroom",
"session_name": "测试群",
"session_kind": "group",
"sender_name": "张三",
"sender_wxid": "wxid_customer",
"msg_type": "image",
"image_url": "http://192.168.3.10:8000/plugins/draw/files/demo.png",
"mention_sender": true,
"reply_to_msg_svr_id": "1234567890"
}
}
POST /send/envelope/batch
一次请求写入多条结构化出站 envelope。
请求体数组键支持 messages 或 envelopes。
请求示例:
{
"messages": [
{
"target": {
"session_id": "123456@chatroom",
"session_name": "测试群",
"session_kind": "group"
},
"sender": {
"wxid": "wxid_customer",
"name": "张三"
},
"content": {
"msg_type": "text",
"text": "第一条结构化消息"
},
"reply": {
"mention_sender": true,
"reply_to_msg_svr_id": "1234567890"
}
}
]
}
成功响应:
{
"results": [
{
"queued": true,
"id": 100,
"protocol": "envelope",
"normalized": {
"session_id": "123456@chatroom",
"session_name": "测试群",
"session_kind": "group",
"sender_name": "张三",
"sender_wxid": "wxid_customer",
"msg_type": "text",
"mention_sender": true,
"reply_to_msg_svr_id": "1234567890"
}
}
],
"count": 1
}
会话与队列元数据
GET /sessions
列出从已解密微信数据库映射出的已知会话。
响应示例:
{
"sessions": [
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"kind": "group"
},
{
"session_id": "wxid_xxx",
"session_name": "李四",
"kind": "private"
}
],
"count": 2
}
GET /queue/stats
返回本地出站队列状态计数。
响应示例:
{
"pending": 3,
"sent": 42,
"failed": 1
}
GET /queue/messages
从 SDK 本地 SQLite 队列库返回出站队列明细。
该接口主要供 agent-console 查看 SDK 本地待发送队列,而不是只展示聚合计数。
查询参数:
status: 可选,空值表示不过滤limit: 整数,默认100,范围1-500
请求示例:
curl "http://127.0.0.1:5080/queue/messages?status=pending&limit=50"
响应示例:
{
"items": [
{
"id": 7,
"session_id": "123456@chatroom",
"session_name": "测试群",
"sender_name": "客服",
"sender_wxid": "wxid_customer",
"mention_sender": 1,
"reply_to_msg_svr_id": "1234567890",
"session_kind": "group",
"reply_text": "你好",
"image_path": "",
"image_url": "",
"msg_type": "text",
"source_message": {
"message_id": "1234567890"
},
"delivery": {
"channel": "wechat",
"command_id": "wxbot-reply-12345"
},
"idempotency_key": "wxbot-reply-12345",
"status": "pending",
"error": "",
"attempt_count": 0,
"claimed_ts": 0,
"lease_until_ts": 0,
"created_ts": 1776681000,
"sent_ts": null
}
],
"count": 1
}
说明:
mention_sender在本地队列表中以0/1保存。- 排序为
created_ts DESC, id DESC。 - 如果队列库尚未初始化,SDK 返回空列表而不是
404。
GET /debug/trigger-config
返回当前群消息采集调试开关状态。
该接口供 agent-console 确认群消息是否仅限 @ 机器人时进入队列,还是允许所有群消息进入队列。
响应示例:
{
"group_require_at_me": false,
"group_capture_mode": "all_group_messages",
"my_names": ["bot", "机器人"],
"config_path": "C:\\Users\\...\\config.json"
}
语义:
group_require_at_me=true: 只采集明确 @ 机器人的群消息。group_require_at_me=false: 采集所有群消息。group_capture_mode: 同一状态的人类可读描述。
POST /debug/trigger-config
更新运行时群消息采集调试开关,并写回 config.json。
请求体:
{
"group_require_at_me": false
}
成功响应:
{
"group_require_at_me": false,
"group_capture_mode": "all_group_messages",
"my_names": ["bot", "机器人"],
"config_path": "C:\\Users\\...\\config.json",
"saved": true
}
校验错误示例:
{
"error": "group_require_at_me required"
}
运维说明:
- 该开关只影响后续群消息扫描。
- 默认推荐值是
true。 - 设置为
false主要用于排查意外自动回复触发问题。
GET /logs
读取近期 SDK 日志。
查询参数:
lines: 默认100,最大500
响应示例:
{
"lines": [
"[19:40:44] [main] starting HTTP API on 127.0.0.1:5080"
],
"count": 1
}
图片
GET /images/<path>
返回 SDK 图片基础目录下的已解密图片文件。
通常配合入站图片消息中的 image_path 使用。
群成员名册
GET /ext/roster/groups
从已解密的 contact.db 列出权威群会话。
响应示例:
{
"ok": true,
"sessions": [
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"kind": "group",
"count": 0,
"last_ts": null,
"owner": "wxid_owner",
"avatar": {
"big_head_url": "https://wx.qlogo.cn/mmhead/.../0",
"small_head_url": "https://wx.qlogo.cn/mmhead/.../132",
"head_img_md5": "",
"cache_md5": "b83ce6640fbeb97ce5001790546f451e",
"cache_url": "/ext/roster/avatars/2106355209%40chatroom",
"cached": true,
"size": 5463,
"content_type": "image/jpeg",
"update_time": 1753248121
}
}
],
"count": 1
}
GET /ext/roster/groups/<session_id>/members
返回权威群成员名册以及消息历史统计。
响应示例:
{
"ok": true,
"session_id": "123456@chatroom",
"source_kind": "authoritative_group_roster",
"is_membership_roster": true,
"message_scope": "text_only",
"source_note": "候选列表来自已解密 contact.db 的真实群成员名册;发言列表仅表示当前保留消息中的历史发言统计。",
"candidates": [
{
"wxid": "wxid_xxx",
"name": "张三",
"alias": "",
"remark": "",
"nick_name": "张三",
"avatar": {
"big_head_url": "https://wx.qlogo.cn/mmhead/.../0",
"small_head_url": "https://wx.qlogo.cn/mmhead/.../132",
"head_img_md5": "",
"cache_md5": "ce210c0289fc727dcbf116d581373cee",
"cache_url": "/ext/roster/avatars/wxid_xxx",
"cached": true,
"size": 4773,
"content_type": "image/jpeg",
"update_time": 1753242004
},
"msg_count": 18,
"first_ts": 1776000000,
"last_ts": 1776681000,
"has_history": true
}
]
}
GET /ext/roster/avatars/<username>
从已解密的 head_image.db 返回缓存头像图片字节。样本运行数据中 image_buffer 为普通图片字节,因此接口会按探测到的 Content-Type 直接返回,例如 image/jpeg 或 image/png。
当群或成员响应中的 avatar.cached 为 true 时,使用 avatar.cache_url 取头像。
成员事件与 Webhook 订阅
GET /events
拉取 SDK 类型事件。
查询参数:
cursor: 整数,默认0limit: 整数,默认100,最大500event_type: 可选session_id: 可选
当前重要事件类型:
group.member.joinedgroup.member.left
GET /events/stream
类型事件 SSE 流。
兼容说明:
- 这是旧版兼容接口。
- 新接入建议使用
GET /stream。 /events/stream不包含入站消息正文。
请求示例:
curl -N "http://127.0.0.1:5080/events/stream?cursor=0"
消息帧格式:
id: 12
event: group.member.joined
data: {"id":12,"event_type":"group.member.joined",...}
GET /event-subscriptions
列出 SDK 侧类型事件 webhook 订阅。
查询参数:
event_type: 可选session_id: 可选,空字符串表示该事件类型的全局订阅
POST /event-subscriptions
创建或更新一个类型事件 webhook 订阅。
请求示例:
{
"event_type": "group.member.joined",
"session_id": "123456@chatroom",
"target_url": "https://example.com/webhooks/wxbot-member-events",
"enabled": true
}
响应示例:
{
"ok": true,
"subscription": {
"id": 3,
"event_type": "group.member.joined",
"session_id": "123456@chatroom",
"target_url": "https://example.com/webhooks/wxbot-member-events",
"enabled": 1
}
}
DELETE /event-subscriptions/<subscription_id>
按数字 id 删除订阅。
群成员设置
GET /group-members/settings/<session_id>
读取 SDK 侧单群成员事件行为设置。
响应示例:
{
"session_id": "123456@chatroom",
"welcome_enabled": 1,
"welcome_template": "欢迎 {{member_name}} 加入群聊",
"welcome_mention": 0,
"updated_ts": 1776681000
}
POST /group-members/settings/<session_id>
更新群成员加入/离开相关设置。
请求示例:
{
"welcome_enabled": true,
"welcome_template": "欢迎 {{member_name}}",
"welcome_mention": false
}
用途:
- 成员进群欢迎语
- 后续审计或事件处理配置
Persona 提取支持
POST /ext/persona/messages
直接从已解密微信消息数据库中,采集某个会话内某个成员的人设提取消息样本。
该接口供 agent-console 的 persona 提取或类似工具使用。
请求体:
{
"session_id": "123456@chatroom",
"target_wxid": "wxid_xxx",
"target_name": "张三",
"days_limit": 90,
"max_messages": 2000
}
规则:
days_limit = 0表示不限制时间范围。max_messages = 0表示不限制消息数量。- 当前实现只采集文本消息。
响应示例:
{
"ok": true,
"session_id": "123456@chatroom",
"target_wxid": "wxid_xxx",
"target_name": "张三",
"source_kind": "wechat_decrypted_message_db",
"message_scope": "text_only",
"full_extract": false,
"days_limit": 90,
"max_messages": 2000,
"count": 128,
"messages": [
{
"sender_wxid": "wxid_xxx",
"sender_name": "张三",
"text": "你好",
"timestamp": "2026-04-20 10:00:00",
"ts": 1776650400
}
],
"first_timestamp": "2026-01-20 10:00:00",
"last_timestamp": "2026-04-20 10:00:00"
}
群报告
GET /ext/reports/subscriptions
列出所有群报告订阅。
POST /ext/reports/subscriptions
创建或更新一个群报告订阅。
请求示例:
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"daily_enabled": true,
"monthly_enabled": false,
"daily_hour": 9,
"monthly_day": 1,
"tz": "Asia/Shanghai"
}
DELETE /ext/reports/subscriptions/<session_id>
删除一个群报告订阅。
GET /ext/reports/preview/<session_id>
预览一份报告,不发送。
查询参数:
report_type:daily或monthlysession_name: 可选覆盖值
GET /ext/reports/messages/<session_id>
返回一份日报或月报时间窗口背后的原始聊天记录。
查询参数:
report_type:daily或monthlysession_name: 可选覆盖值date: 可选YYYY-MM-DD,仅日报使用year_month: 可选YYYY-MM,仅月报使用
响应示例:
{
"ok": true,
"session_id": "123456@chatroom",
"session_name": "测试群",
"report_type": "daily",
"period": "2026-04-20",
"start_ts": 1776614400,
"end_ts": 1776700800,
"count": 2,
"messages": [
{
"ts": 1776650400,
"timestamp": "2026-04-20 10:00:00",
"sender_wxid": "wxid_xxx",
"sender_name": "张三",
"msg_type": "text",
"text": "你好"
},
{
"ts": 1776650500,
"timestamp": "2026-04-20 10:01:40",
"sender_wxid": "wxid_yyy",
"sender_name": "李四",
"msg_type": "image",
"text": "[图片]"
}
]
}
说明:
- 日报不传
date时,默认前一天。 - 月报不传
year_month时,默认上个月。 - 该接口返回原始记录,不返回
/ext/reports/preview使用的汇总文本。
POST /ext/reports/send
生成并入队发送一份报告。
请求示例:
{
"session_id": "123456@chatroom",
"session_name": "测试群",
"report_type": "daily"
}
重要行为:
- 报告内容从已解密微信数据库生成。
- 不依赖
agent-console对话轮次。 - 如果需要原始记录而不是摘要文本,请使用
GET /ext/reports/messages/<session_id>。
只读查询扩展
POST /ext/query/read
对 SDK 本地 SQLite 数据库执行受限只读 SQL 查询。
该接口用于减少内部扩展时反复修改 SDK 代码,同时保留安全边界。
允许的数据库:
messagecontactqueue
限制:
- 只允许
SELECT或WITH查询。 - 不允许分号分隔的多语句。
- 不允许写入或修改 schema。
limit上限为500。
请求示例:
{
"database": "message",
"sql": "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name",
"limit": 20
}
响应示例:
{
"ok": true,
"database": "message",
"db_path": "C:\\...\\message_0.db",
"columns": ["name"],
"rows": [
{"name": "Name2Id"},
{"name": "Msg_xxxxx"}
],
"count": 2,
"limit": 20,
"truncated": false
}
建议:
- 稳定产品功能优先使用专用接口。
/ext/query/read适合内部调试、数据检查或临时扩展场景。
建议接入顺序
典型外部系统接入流程:
- 调用
GET /status。 - 拉取
GET /sessions或GET /ext/roster/groups。 - 订阅
GET /stream。 - 通过
POST /send或POST /send/envelope发送出站消息。 - 通过
/event-subscriptions管理群 webhook。 - 通过
/ext/reports/*管理群报告。
旧版兼容:
GET /messages、GET /messages/stream、GET /events和GET /events/stream仍可用于阶段性迁移。- 新消费方应以
/stream作为主要入站消息和事件通道。
已知数据语义
- 群成员候选列表来自已解密
contact.db。 - Persona 提取样本来自已解密
message_0.db。 - 报告生成来自已解密
message_0.db。 - 出站队列状态来自 SDK 本地队列库。
兼容提醒
新增 SDK 接口时,应同步更新:
api/server.pydocs/README.md- 本文档
这样下游调用方才能与实际 SDK 协议保持一致。