Bot API 文档

Bot API 参考

从申请、鉴权、Webhook / 长轮询到 sendMessage、富消息与官方 SDK——面向开发者的完整接入文档。

API 概览

Base URL
https://www.49chatapp.com
鉴权
Authorization: Bearer sbot_<token>
API 版本
v1
更新日期
2026-05

产品定位与接入边界

49热聊 开放平台为开发者提供机器人身份、消息路由、投递保障与安全边界。机器人业务逻辑运行在你自己的服务上,平台负责把消息可靠地送到你的代码、并把你的回应送回会话。

审核后开放

任何登录用户都可提交创建申请,机器人在通过开放平台审核后获得 Bot Token,避免滥用与冒名。

业务自托管

机器人业务运行在你自己的服务上,49热聊 不托管业务代码,也不要求你部署在指定基础设施。

鉴权完全隔离

所有 Bot API 通过 Bot Token 调用,与终端用户身份完全隔离,便于自动化系统直接接入。

可靠异步投递

Update 通过异步队列分发,平台保证至少一次送达;失败按固定节奏重试,仍失败可在投递日志中重投。

能力总览

  • 消息收发 — 文本、图片、文件、视频、音频、语音、视频笔记、动图、贴纸、骰子、投票、联系人、位置、地点、媒体组等 15+ 消息类型。
  • 编辑 / 撤回 / 转发 — editMessage、editMessageReplyMarkup、deleteMessage、forwardMessage、copyMessage,全部触发对应事件投递。
  • 富交互 — InlineKeyboard 按钮回调(callback_query / answerCallbackQuery)、Inline Mode(inline_query / answerInlineQuery)、命令菜单。
  • 群读取与治理 — getChat 系、setChat 系、置顶、踢人 / 拉黑 / 解封、sendChatAction、好友申请审核(manual)。
  • 事件订阅 — message、edited_message、message_deleted、message_read、message_delivered、callback_query、inline_query、friend_request、my_chat_member / chat_member / chat_join_request。
  • 两种投递模式 — Webhook 主动 POST 或 getUpdates 长轮询,两者互斥;调用 setWebhook / deleteWebhook 自动切换。
  • Token 治理 — 审核通过后签发,明文仅返回一次;支持轮换、吊销与 token_prefix 审计可见。
  • 速率配额 — 全局默认与机器人级配额叠加;超限返回 429 + Retry-After + X-BotRateLimit-Remaining。
  • 观测与排障 — 投递日志按状态分页查询,dead_letter 可手动重投;近 24 小时投递与调用指标可读。
  • 官方 SDK — Node.js / TypeScript 与 Java 双 SDK,内置签名、去重、命令路由、长轮询与一步多媒体上传。

快速开始

从提交申请到收到第一条 Update,按下面四步完成最短链路。

步骤 01

提交申请

在「开发者控制台」登录后提交,或在 49热聊 App 内「我的机器人」中创建;任一入口都会进入同一份审核队列。

  • 任何登录用户均可发起申请
  • 名称、用户名、描述、头像由开发者自填
  • 提交后状态为 pending,等待开放平台审核
步骤 02

等待审核

开放平台审核通过后会签发 Bot Token,并在你的「开发者控制台」中提供一次性明文读取。

  • 审核通过 → 颁发 sbot_ 前缀 Token
  • 明文仅首次返回,服务端只存 Token 哈希
  • 随时可在控制台轮换、吊销
步骤 03

配置 Webhook(或长轮询)

回到「开发者控制台」读取一次性 Token;推荐配置 HTTPS Webhook,没有公网 IP 也可改用 getUpdates 长轮询。

  • Webhook:URL 必须 https://,secret_token 用于 HMAC-SHA256
  • 长轮询:deleteWebhook → 调用 getUpdates 拉取 Update
  • 两种模式互斥,平台自动维护 delivery_mode
步骤 04

开始收发

把机器人加入会话,发送 / 命令或 @机器人 触发 Update;调用 sendMessage / sendPhoto 等接口回消息,并可随时编辑或撤回自己发出的消息。

  • 群聊默认 Privacy Mode 开启,仅命令 / @ / 回复 / 服务事件入站;私聊全量入站
  • 消息类型覆盖文本、图片、文件、视频、语音、贴纸、骰子、投票、联系人、地点、媒体组 等
  • 富交互:InlineKeyboard 按钮回调、Inline Mode、命令菜单
  • editMessage / deleteMessage 仅作用于本机器人发出的消息

接入流程

1

提交创建申请

在「开发者控制台」或 49热聊 App 内填写机器人名称、用户名、描述与用途说明并提交,状态进入 pending。

2

开放平台审核

平台核对身份与用途说明后通过或拒绝,结果通过 review_status 在控制台返回,被拒绝时附带原因。

3

读取 Token 并配置投递

审核通过后第一次进入控制台会展示明文 Token(仅一次);同时可登记 Webhook、配置 allowed_updates 与 IP 白名单。

4

加入会话并联调

把机器人拉入私聊或群聊,发送测试消息观察 Update 投递,调用 sendMessage 回消息即可完成最小闭环。

最小闭环清单

Bot Token

鉴权

前缀 `sbot_`,明文仅在审核通过后第一次返回;服务端只存哈希,可随时轮换或吊销。

两种投递模式

入站

`setWebhook` 配置 HTTPS 后平台主动 POST;或 `deleteWebhook` 切到 `polling`,用 `getUpdates` 长轮询拉取。两者互斥,由 `Bot.delivery_mode` 维护。

消息收发

出站

文本 + 图片 / 文件 / 视频 / 音频 / 语音 / 视频笔记 / 动图 / 贴纸 / 骰子 / 投票 / 联系人 / 位置 / 地点 / 媒体组;发送后可 `editMessage` / `deleteMessage` / `editMessageReplyMarkup`。

富交互

交互

InlineKeyboard `callback_data` 触发 `callback_query`,5s 内调 `answerCallbackQuery`;Inline Mode 通过 `answerInlineQuery` 应答 `inline_query`。

群治理

治理

`getChat*` 读取群信息;`setChatTitle / Description / Photo`、`pinChatMessage` 系、`kickChatMember` / `banChatMember` 需机器人在该群为群主或管理员。

Privacy Mode

可见性

群聊仅投递:`/` 开头命令、文本含 `@username`、回复机器人消息或 mentions 命中机器人;私聊全量投递。

速率配额

稳定性

全局默认 + 单机器人配额叠加;超限返回 429 并带 `Retry-After` 与 `X-BotRateLimit-Remaining`。

API 约定

所有 Bot API 共享同一份约定:Base URL、鉴权方式、请求 / 响应封装、时间格式、错误结构、限流头与命名规范。 后续每个端点只描述其特有的参数与返回字段,公共部分以本节为准。

Base URL

HTTPS Only

生产环境通过 HTTPS 访问,端点以 /api/v1/bots/** 为前缀。

  • ·生产:见页面顶部 Base URL 标签
  • ·所有请求与回调必须使用 HTTPS

鉴权

Bearer Token

业务接口使用机器人 Bot Token,开发者接口使用账号 JWT;两类 Token 完全隔离。

  • ·Bot 业务:Authorization: Bearer sbot_<token>
  • ·开发者管理:Authorization: Bearer <jwt>
  • ·Token 仅在审核通过后第一次返回明文

请求体格式

application/json

所有 POST / PATCH 请求体均为 UTF-8 JSON;GET 参数走 query string。

  • ·Content-Type: application/json; charset=utf-8
  • ·字段命名使用 snake_case
  • ·布尔传 true / false,时间见下

时间与时区

Unix Timestamp

所有时间戳为 UTC,Update 载荷使用秒级 Unix 时间,部分响应字段使用毫秒,需以字段名区分。

  • ·date: Unix 秒(如 1735692000)
  • ·createdAt / updatedAt: ISO 8601 字符串
  • ·客户端按需自行转换至本地时区

分页

page / pageSize

列表型端点统一使用 page / pageSize 参数,响应同时返回 total。

  • ·默认 page=1,pageSize=20
  • ·pageSize 最大 100
  • ·响应:{ items, total, page, pageSize }

幂等键

update_id

Webhook / 长轮询投递的 Update 携带稳定的 update_id 作为幂等键,重试不变;客户端请按此去重。

  • ·update_id 在重试时保持一致
  • ·请用 Redis / DB 持久化去重

错误结构

success: false

失败响应统一返回 { success:false, code, message },HTTP 状态与 code 含义对齐。

  • ·400 VALIDATION / 401 INVALID_BOT_TOKEN
  • ·403 FORBIDDEN / 404 NOT_FOUND
  • ·409 CONFLICT / 429 BOT_RATE_LIMIT

命名规范

snake_case

HTTP 协议层使用 snake_case;官方 SDK 转换为各语言风格(Node.js camelCase,Java camelCase)。

  • ·HTTP 字段:chat_id / message_id / file_id
  • ·Node SDK:chatId / messageId / fileId
  • ·SDK 与 HTTP 行为一致,只换命名风格

统一响应封装

所有 Bot API 的响应都遵循以下结构。成功时 success=true, 业务数据在 data;失败时 success=falsecode 对应错误码表

JSON
// 成功
{
  "success": true,
  "data": {
    "message_id": "6530ab12c9a0ff00123abc88",
    "chat": { "id": "6530ab12c9a0ff00123abc55", "type": "group" },
    "from": { "id": "<bot_user_id>", "is_bot": true },
    "text": "Hello",
    "date": 1735692000
  }
}

// 失败
{
  "success": false,
  "code": "VALIDATION",
  "message": "chat_id is required"
}

限流与响应头

达到机器人级配额时返回 429 BOT_RATE_LIMIT,并通过响应头声明退避时长。

响应头示例说明
Retry-After1建议退避秒数;遇到 429 时务必参考此值再重试。
X-BotRateLimit-Remaining0当前窗口内剩余可发送次数;为 0 表示已触顶。
X-BotRateLimit-Reset1735692060当前限流窗口重置的 Unix 秒时间戳。
X-StarIM-Request-Id<uuid>请求唯一 ID,遇问题反馈时请同时提供该值便于追溯。

HTTP API 参考

按鉴权方式分为两组:开发者端用账号 JWT 管理自己申请的机器人;Bot 业务端用机器人 Bot Token (Authorization: Bearer sbot_<token>) 调用业务接口。所有路径以 /api/v1/bots/** 为前缀。公共行为参考API 约定

开发者端点(JWT)

以账号登录态调用,用于申请机器人、查看列表、读取一次性 Token、登记或删除 Webhook。

POST/api/v1/bots/applicationsJWT

提交机器人申请

登录用户提交创建申请,等待平台审核。

  • ·必填:`name` (<=100)
  • ·可选:`username` (<=64,全局唯一)、`description`、`avatar`、`scopes[]`
  • ·默认 `scopes = ["messages:send", "messages:receive"]`
  • ·返回:机器人对象(`review_status=pending`)
GET/api/v1/bots/myJWT

我的机器人列表

列出当前开发者提交的所有机器人,含状态与 Token 前缀。

  • ·返回:`items[]`,每项含 `review_status`、`status`、`has_token`、`token_prefix`
GET/api/v1/bots/my/:idJWT

机器人详情(含一次性 Token)

审核通过后首次读取会返回 `one_time_token`,读后即销毁(7 天有效)。

  • ·返回:机器人基础信息、`webhook`(脱敏)、`one_time_token?`
  • ·`one_time_token` 仅首次访问返回,请妥善保存
POST/api/v1/bots/my/:id/webhookJWT

登记 Webhook(开发者)

使用账号 JWT 为自己的机器人配置 Webhook,无需使用 Bot Token。

  • ·必填:`url` (必须以 `https://` 开头)
  • ·可选:`secret_token`、`allowed_updates[]`、`allowed_ips[]`
  • ·返回:`webhook`(脱敏,去除 `secret_token`)
DELETE/api/v1/bots/my/:id/webhookJWT

删除 Webhook(开发者)

移除当前机器人的 Webhook 配置,停止接收 Update。

  • ·返回:`bot_id`
GET/api/v1/bots/my/:id/deliveriesJWT

查看 Webhook 投递日志

分页查看机器人最近的 Webhook 投递记录,辅助排查失败或死信。

  • ·可选查询:`page`、`pageSize` (默认 20,最大 100)、`status` (`pending` / `delivering` / `success` / `failed` / `dead_letter`)
  • ·返回:`items[]`(含 `update_id`、`status`、`attempts`、`last_error`、`dead_letter_at`)、`total`、`page`、`pageSize`
POST/api/v1/bots/my/:id/regenerate-tokenJWT

重新生成 Bot Token

签发新 Token 并立即吊销旧 Token;返回的 `one_time_token` 仅本次响应可读,请妥善保存。

  • ·返回:`bot`、`one_time_token`(一次性明文)
  • ·限频:5 次 / 5 分钟;旧 Token 立即失效,正在使用旧 Token 的进程会收 401,请及时切换
PATCH/api/v1/bots/my/:idJWT

更新机器人资料

审核通过后调整机器人名称 / 头像 / 描述 / Profile 元信息。

  • ·可选:`name`(显示名,≤100,非空,可中文;@username 不可自助改)
  • ·可选:`avatar`、`description`、`short_description` (≤120)、`about` (≤512)、`cover_url`
  • ·可选:`links.{website, privacy_policy, terms_of_service, support}`、`contact.{organization, email, phone}`
  • ·可选:`supports_inline_queries` (Boolean,开启后才会收 `inline_query`)、`friend_request_mode` (`auto_accept` / `auto_reject` / `manual`)
  • ·返回:更新后的 `bot` 对象(脱敏)

Bot 业务端点(Bot Token)

使用机器人自己的 Token 调用。请求头 Authorization: Bearer sbot_<token>;端点按主题分组,可点目录跳转。

机器人信息 / Profile

13 个端点

查看自身、设置命令菜单与短 / 长描述、好友申请策略。

GET/api/v1/bots/meBot Token

获取当前机器人信息

基于 Bot Token 解析并返回机器人基础信息。

  • ·返回:`id`、`name`、`username`、`review_status`、`status`、`scopes`、`system_user_id`
POST/api/v1/bots/setMyShortDescriptionBot Token

设置短描述

设置机器人在主页 / 私聊「ⓘ」面板顶部展示的一句话短描述(≤120)。

  • ·可选:`short_description`(≤120,留空清空)
  • ·返回:`bot_id` / `short_description`
GET/api/v1/bots/getMyShortDescriptionBot Token

读取短描述

与 `setMyShortDescription` 配对,便于客户端回填。

  • ·返回:`{ short_description }`
POST/api/v1/bots/setMyDescriptionBot Token

设置长描述

设置机器人在「关于」面板的多行说明。

  • ·可选:`description`(≤512,留空清空)
  • ·返回:`bot_id` / `about`
GET/api/v1/bots/getMyDescriptionBot Token

读取长描述

与 `setMyDescription` 配对。

  • ·返回:`{ description }`(即 `Bot.about`)
POST/api/v1/bots/setMyCommandsBot Token

设置命令菜单

配置 `/start`、`/help` 等命令;App 内输入 `/` 会拉出下拉提示。可按 `scope` / `language_code` 分组。

  • ·必填:`commands` (`{ command, description }[]`,1..100 项;command 仅 a-z0-9_,1..32 字符)
  • ·可选:`scope`(`default` / `all_private_chats` / `all_group_chats` / `all_chat_administrators` 等,或 `{ type, chat_id?, user_id? }`)
  • ·可选:`language_code` (BCP-47)
  • ·返回:`{ ok: true }`
GET/api/v1/bots/getMyCommandsBot Token

读取命令菜单

与 `setMyCommands` 配对,可按 `scope` / `language_code` 过滤。

  • ·可选 query:`scope`、`language_code`
  • ·返回:`{ commands }`
POST/api/v1/bots/deleteMyCommandsBot Token

删除命令菜单

删除某个 `scope` + `language_code` 组合下的命令清单。

  • ·可选:`scope`、`language_code`
  • ·返回:`{ ok: true }`
POST/api/v1/bots/setMyFriendRequestModeBot Token

设置好友申请策略

配置 `auto_accept` / `auto_reject` / `manual`;`manual` 时由机器人通过 `answerFriendRequest` 决定。

  • ·必填:`friend_request_mode`
  • ·返回:`{ friend_request_mode }`
GET/api/v1/bots/getMyFriendRequestModeBot Token

读取好友申请策略

与 `setMyFriendRequestMode` 配对。

  • ·返回:`{ friend_request_mode }`
GET/api/v1/bots/getFriendRequestsBot Token

查看好友申请列表

列出当前机器人收到的 pending 申请;需要先把策略改为 `manual`。

  • ·返回:`items[]`(含 `id`、`fromUserId`、`fromUsername`、`requestMessage`、`source`、`status`)
POST/api/v1/bots/answerFriendRequestBot Token

处理好友申请

在 `manual` 模式下机器人主动接受 / 拒绝某个好友申请;接受后双方关系自动生效。

  • ·必填:`friendship_id`、`action` (`accept` / `reject`)
  • ·返回:处理结果
POST/api/v1/bots/verify-token无(请求体带 token)

校验 Bot Token

调试用:使用请求体中的 `token` 参数校验有效性(公开端点)。

  • ·必填:`token`
  • ·返回:`bot` 对象或错误

Webhook / 长轮询

4 个端点

webhook 配置、查询、长轮询 getUpdates。

POST/api/v1/bots/setWebhookBot Token

配置 Webhook

使用 Bot Token 直接配置 Webhook;与开发者 JWT 接口二选一。调用后机器人投递模式自动切到 `webhook`。

  • ·必填:`url` (必须 HTTPS)
  • ·可选:`secret_token`、`allowed_updates[]` (默认 `["message"]`;可含 `edited_message` / `message_deleted` / `callback_query`)、`allowed_ips[]`
  • ·返回:`webhook`(脱敏)
  • ·副作用:`Bot.delivery_mode = webhook`
POST/api/v1/bots/deleteWebhookBot Token

删除 Webhook

移除当前 Webhook 配置,停止主动 POST 投递;机器人投递模式自动切到 `polling`,可改用 `getUpdates` 拉取。

  • ·返回:`bot_id` / `delivery_mode = "polling"`
POST/api/v1/bots/getUpdatesBot Token

getUpdates 长轮询

在 `polling` 模式下拉取等待中的 Update。无公网 IP 也能起 bot;与 webhook 模式互斥(webhook 模式下调用该端点会返回 409)。

  • ·可选:`offset`(拉取 `update_seq >= offset` 的条目;推荐用「上一批最后一条 update_seq + 1」做下次 offset,等价 ack)
  • ·可选:`limit`(1..100,默认 100)
  • ·可选:`timeout`(long-poll 秒数,0 立即返回,最大 50;默认 0)
  • ·可选:`allowed_updates[]`(如 `["message","callback_query"]`,缺省 = 全部)
  • ·返回:`{ updates: [{ update_id, type, message?, callback_query?, update_seq }] }`
  • ·冲突:webhook 模式下调用 → 409 `Conflict: can't use getUpdates method while webhook is active`
GET/api/v1/bots/getWebhookInfoBot Token

查询 Webhook 摘要

返回当前 Webhook 配置摘要 + 平台出站 IP,方便客户在防火墙做白名单。

  • ·返回:`{ url, has_custom_certificate, pending_update_count, allowed_updates, last_error_date, last_error_message, max_connections, platform_egress_ips[] }`
  • ·`platform_egress_ips` 为平台对你的 Webhook 发起请求时使用的出站 IP,便于在防火墙做白名单

消息发送

16 个端点

文本、富媒体与扩展消息类型。

POST/api/v1/bots/sendMessageBot Token

发送文本消息

向指定会话发送文本消息,对外以机器人系统账号身份发送。

  • ·必填:`chat_id` (会话 ID)、`text` (文本内容)
  • ·返回:消息对象(含 `message_id`、`chat`、`from`、`date`)
  • ·多媒体请使用 `sendPhoto / sendDocument / sendVideo / sendAudio`
POST/api/v1/bots/sendPhotoBot Token

发送图片消息

以图片形式发送已上传的文件,`file_id` 来源于 `/files/complete`。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`caption` (图片说明文字)、`width` / `height` (像素,数值,>0 时写入 `metadata.width / height`)
  • ·`file_id` 对应 File 文档若已写入 `metadata.dimensions`,平台会自动补齐
  • ·返回:消息对象(`message_type=image`)
POST/api/v1/bots/sendDocumentBot Token

发送文件消息

以文档 / 附件形式发送已上传的文件。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`caption`、`thumbnail_url` (文件缩略图 URL,写入 `metadata.thumbnailUrl`)
  • ·返回:消息对象(`message_type=file`)
POST/api/v1/bots/sendVideoBot Token

发送视频消息

以视频形式发送已上传的文件。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`caption`、`duration` (秒)、`width` / `height` (像素)、`thumbnail_url`
  • ·所有可选字段 `>0` / 非空时才写入 `metadata.*`;未提供时客户端会在播放时自动读取元数据
  • ·返回:消息对象(`message_type=video`)
POST/api/v1/bots/sendAudioBot Token

发送语音消息

以音频 / 语音形式发送已上传的文件。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`caption`、`duration` (秒,语音气泡显示用)、`performer` (表演者 / 上传者)、`title` (曲目 / 标题)
  • ·`performer` / `title` 主要面向音乐 / 播客场景,进入 `metadata` 与 Webhook Update `message.file`
  • ·返回:消息对象(`message_type=audio`)
POST/api/v1/bots/sendLocationBot Token

发送位置消息

发送一个包含经纬度和可选地名的位置消息。

  • ·必填:`chat_id`、`latitude`、`longitude`
  • ·可选:`name` (地点名)、`address` (结构化地址)
  • ·返回:消息对象(`message_type=location`)
POST/api/v1/bots/sendVenueBot Token

发送地点

在 `sendLocation` 基础上要求标题;客户端会以「带标题地址卡片」样式展示。

  • ·必填:`chat_id`、`latitude`、`longitude`、`title`
  • ·可选:`address`、`reply_markup`
  • ·返回:消息对象(`message_type=venue`,`metadata.isVenue=true`)
POST/api/v1/bots/sendVoiceBot Token

发送语音消息

与 `sendAudio` 同样上传后用 `file_id` 发送;客户端按「语音气泡」样式渲染。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`caption`、`duration` (秒)、`performer`、`title`
  • ·返回:消息对象(`message_type=voice`)
POST/api/v1/bots/sendVideoNoteBot Token

发送视频笔记

圆形短视频;客户端会按 `width = height` 圆形播放器渲染。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`duration` 或 `length` (秒)、`width` / `height` (像素)、`thumbnail_url`
  • ·返回:消息对象(`message_type=video_note`)
POST/api/v1/bots/sendAnimationBot Token

发送动图

通常是 GIF / MP4 短动画;客户端按视频自动循环播放。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`caption`、`duration` (秒)、`width` / `height` (像素)、`thumbnail_url`
  • ·返回:消息对象(`message_type=animation`)
POST/api/v1/bots/sendStickerBot Token

发送贴纸

`file_id` 来源同其他多媒体;推荐 webp / lottie。

  • ·必填:`chat_id`、`file_id`
  • ·可选:`width` / `height`、`thumbnail_url`
  • ·返回:消息对象(`message_type=sticker`)
POST/api/v1/bots/sendDiceBot Token

发送骰子 / 随机表情

服务端掷点;🎲 / 🎯 / 🏀 / ⚽ / 🎳 / 🎰 等表情各自有不同取值区间。

  • ·必填:`chat_id`
  • ·可选:`emoji` (默认 `🎲`;🎰 → 1–64,⚽/🏀 → 1–5,其余默认 1–6)、`reply_markup`
  • ·返回:消息对象(`message_type=dice`;`metadata.diceEmoji` / `metadata.diceValue`,`text` 形如 `🎲 4`)
POST/api/v1/bots/sendPollBot Token

发送投票

当前仅支持 `regular` / `quiz` 两种类型;客户端以投票气泡渲染。

  • ·必填:`chat_id`、`question`、`options[]` (2..12)
  • ·可选:`is_anonymous` (默认 `true`)、`type` (`regular` / `quiz`)、`correct_option_id` (`quiz` 时必填)、`reply_markup`
  • ·返回:消息对象(`message_type=poll`;`metadata.poll = { question, options, ... }`)
POST/api/v1/bots/sendContactBot Token

发送联系人名片

客户端以名片气泡展示电话号码与姓名。

  • ·必填:`chat_id`、`phone_number`、`first_name`
  • ·可选:`last_name`、`reply_markup`
  • ·返回:消息对象(`message_type=contact`;`metadata.contact = { phone_number, first_name, last_name }`)
POST/api/v1/bots/sendMediaGroupBot Token

发送媒体组

将 2..10 条媒体作为一组发送;平台会拆分为多条独立消息存储,仅最后一条带 `reply_markup`。

  • ·必填:`chat_id`、`media[]` (2..10)
  • ·`media[i]` 必填:`type` (`photo` / `video` / `document` / `audio`)、`media` 或 `file_id`;可选 `caption`
  • ·可选:`reply_markup` (仅作用于最后一条)
  • ·返回:消息对象数组
POST/api/v1/bots/sendChatActionBot Token

sendChatAction

广播聊天状态(`typing` / `upload_photo` 等)。客户端展示 3..5s 的「正在输入…」。

  • ·必填:`chat_id`、`action`(如 `typing` / `upload_photo` / `record_voice` 等)
  • ·返回:`{ ok: true }`

编辑 / 撤回 / 转发

5 个端点

修改、撤回、转发 / 复制本机器人发送的消息。

POST/api/v1/bots/editMessageBot Token

编辑机器人自发消息

仅支持编辑由本机器人(同一 `system_user_id`)发送的文本消息;触发 `edited_message` Update。

  • ·必填:`message_id` (或 `messageId`)、`text` (或 `content`)
  • ·仅限本机器人发送的消息;其他消息返回 403
  • ·编辑成功后消息 `metadata.isEdited=true`,客户端会显示“已编辑”标记
POST/api/v1/bots/deleteMessageBot Token

删除(撤回)机器人自发消息

仅支持删除由本机器人发送的消息;触发 `message_deleted` Update。

  • ·必填:`message_id` (或 `messageId`)
  • ·仅限本机器人发送的消息;其他消息返回 403
  • ·删除后下游会广播 `message.deleted`,客户端从历史中移除
POST/api/v1/bots/editMessageReplyMarkupBot Token

仅编辑 InlineKeyboard

替换某条本机器人消息的 `reply_markup`;不改正文与多媒体。传 `null` 表示清空按钮。

  • ·必填:`message_id`
  • ·`reply_markup` 为 `null` 等价于「清空按钮」;提供新键盘则按 8×8 / `text` 1–64 / `callback_data` ≤ 64 字节 / `url` 必须 `http(s)://` 校验
  • ·仅限本机器人发送的消息;其他消息返回 403
POST/api/v1/bots/forwardMessageBot Token

forwardMessage

将一条历史消息以「转发」形式发到目标会话;机器人需是源 / 目标双会话的活跃成员。

  • ·必填:`from_chat_id`、`chat_id` (目标)、`message_id`
  • ·可选:`caption`
  • ·返回:转发后的消息对象
POST/api/v1/bots/copyMessageBot Token

copyMessage

与 `forwardMessage` 同步对齐,但不带「转发自」标记。

  • ·必填:`from_chat_id`、`chat_id`、`message_id`
  • ·可选:`caption`
  • ·返回:复制后生成的消息对象(`metadata.isForwarded` 不被写入)

文件上传

3 个端点

S3 直传两步法与 getFile 元数据查询。

POST/api/v1/bots/files/upload-credentialsBot Token

申请 S3 直传凭证

为即将上传的多媒体文件获取 S3 预签名凭证;多媒体消息第一步。

  • ·必填:`fileName`、`fileSize` (字节)
  • ·可选:`fileType` (MIME)、`checksum`、`metadata`
  • ·返回:`uploadUrl`、`key`、`headers`、`expiresAt` 等直传参数
POST/api/v1/bots/files/completeBot Token

S3 直传完成登记

客户端完成 PUT 上传后回调登记,获取后续 `sendPhoto / sendDocument` 需要的 `file_id`。

  • ·必填:`key`、`fileName`、`fileSize`
  • ·可选:`fileType`、`checksum`、`category` (默认 `bot`)、`isPublic`
  • ·返回:`file_id`、`url`、`thumbnail_url?` 等文件对象
GET/api/v1/bots/getFileBot Token

getFile

根据 `file_id` 拿到平台文件元数据(含临时下载 URL)。

  • ·必填 query:`file_id`
  • ·返回:`{ file_id, file_name, mime_type, file_size, url, thumbnail_url? }`

富交互 / Inline Mode

2 个端点

InlineKeyboard 应答、Inline Mode 应答。

POST/api/v1/bots/answerCallbackQueryBot Token

应答 InlineKeyboard 点击

收到 `callback_query` Webhook 后 5 秒内必须调一次,否则 App 端按钮一直转圈;同一 `callback_query_id` 仅可应答一次(重复 410)。

  • ·必填:`callback_query_id`
  • ·可选:`text` (≤200,App 显示 toast / alert)、`show_alert` (Boolean)、`url` (打开外链)、`cache_time` (秒)
  • ·返回:`{ ok: true }`
POST/api/v1/bots/answerInlineQueryBot Token

应答 Inline Query

回应用户输入框中针对机器人的 inline 查询;当前 results 仅支持 `article` + `InputTextMessageContent`。

  • ·必填:`inline_query_id`、`results[]` (1..50)
  • ·可选:`cache_time` (秒)、`is_personal` (Boolean)、`next_offset`
  • ·需配合 `Bot.supports_inline_queries = true` 与 `allowed_updates` 含 `inline_query`

群信息读取

4 个端点

查询会话、群成员、群管理员。

GET/api/v1/bots/getChatBot Token

getChat

查询单条会话(私聊或群)的基础信息;机器人必须为该会话的活跃参与者。

  • ·必填 query:`chat_id`(会话 ID)
  • ·返回:`{ id, type, title?, name?, member_count?, pinned_message_id? }`
GET/api/v1/bots/getChatMemberBot Token

getChatMember

查询群内某成员的状态;返回成员资料、所在角色与权限。

  • ·必填 query:`chat_id`、`user_id`
  • ·返回:`{ user: { id, username?, first_name?, is_bot }, status }`
GET/api/v1/bots/getChatMemberCountBot Token

getChatMemberCount

获取群成员人数。

  • ·必填 query:`chat_id`
  • ·返回:`{ count }`
GET/api/v1/bots/getChatAdministratorsBot Token

getChatAdministrators

群管理员(含群主)列表。

  • ·必填 query:`chat_id`
  • ·返回:`administrators[]`(每项含 `user` 与 `status`)

群信息修改

6 个端点

改群名、群描述、群头像;置顶 / 取消置顶。

POST/api/v1/bots/setChatTitleBot Token

setChatTitle

修改群名称;机器人需为群主 / 管理员。

  • ·必填:`chat_id`、`title` (1..128)
  • ·失败 403 时提示机器人需先成为群主或群管理员
POST/api/v1/bots/setChatDescriptionBot Token

setChatDescription

修改群描述;机器人需为群主 / 管理员。

  • ·必填:`chat_id`、`description` (≤512)
POST/api/v1/bots/setChatPhotoBot Token

setChatPhoto

修改群头像 URL;机器人需为群主 / 管理员。

  • ·必填:`chat_id`、`photo` (公开可访问的图片 URL)
  • ·可改用先 `/files/upload-credentials` + `/files/complete` 拿 `objectUrl` 再传
POST/api/v1/bots/pinChatMessageBot Token

pinChatMessage

把某条会话内的消息标记为「置顶」;会写 `Conversation.pinnedMessageId`。

  • ·必填:`chat_id`、`message_id`
  • ·群聊须为群主 / 管理员;私聊默认双方均可置顶
POST/api/v1/bots/unpinChatMessageBot Token

unpinChatMessage

取消单条置顶。

  • ·必填:`chat_id`、`message_id`
POST/api/v1/bots/unpinAllChatMessagesBot Token

unpinAllChatMessages

清空该会话置顶。

  • ·必填:`chat_id`

群治理 / chatAction

4 个端点

踢人 / 拉黑 / 解封;广播聊天状态。

POST/api/v1/bots/sendChatActionBot Token

sendChatAction

广播聊天状态(`typing` / `upload_photo` 等)。客户端展示 3..5s 的「正在输入…」。

  • ·必填:`chat_id`、`action`(如 `typing` / `upload_photo` / `record_voice` 等)
  • ·返回:`{ ok: true }`
POST/api/v1/bots/kickChatMemberBot Token

kickChatMember

把成员移出群(不写黑名单);机器人需为群主 / 群管理员。

  • ·必填:`chat_id`、`user_id`
  • ·失败 403 时提示「机器人需为群主或群管理员」
POST/api/v1/bots/banChatMemberBot Token

banChatMember

移出群并加入群黑名单(先踢后黑),可附 `reason`。

  • ·必填:`chat_id`、`user_id`
  • ·可选:`reason`
POST/api/v1/bots/unbanChatMemberBot Token

unbanChatMember

把成员移出群黑名单(不会自动重新拉入群)。

  • ·必填:`chat_id`、`user_id`

调度成员(增值能力)

2 个端点

在群内列出可调度成员、并以其身份发送文本。默认未开放,需联系开放平台支持申请开通后使用。

GET/api/v1/bots/listChatVirtualMembersBot Token

listChatVirtualMembers(增值能力)

列出群内可被调度的成员。需机器人在群内为活跃成员;该能力默认未对外开放,请通过开放平台支持申请开通后使用。

  • ·必填 query:`chat_id`(群会话 ID)
  • ·可选 query:`limit` (1-200,默认 50)、`offset` (≥0,默认 0)
  • ·返回:`{ items: [{ virtual_user_id, name, username, avatar, joined_at }], pagination: { total, limit, offset } }`
  • ·403:能力未开通、机器人不在该群或会话非群聊
POST/api/v1/bots/simulateSendMessageBot Token

simulateSendMessage(增值能力)

以指定调度成员身份在群里发送一条文本。准入要求与 `listChatVirtualMembers` 一致;首期仅支持文本(`type=text`),长度 ≤ 1000;全部调用均会被记录用于合规追溯。

  • ·必填:`chat_id`、`virtual_user_id`(来自 `listChatVirtualMembers`)、`type=text`、`text` (1-1000)
  • ·可选:`reply_to_message_id`
  • ·返回:与 `sendMessage` 等价的消息对象
  • ·400:参数缺失或文本超长;403:能力未开通 / 目标成员不在该群 / 目标成员状态不可用;404:目标成员不存在

请求示例:sendMessage

文本消息示例;用于展示标准发送方式与返回格式。

cURL
curl -X POST 'https://www.49chatapp.com/api/v1/bots/sendMessage' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "chat_id": "6530ab...9c1",
    "text": "Hello from 49热聊 bot"
  }'

请求示例:sendPhoto(多媒体 4 步法)

sendDocument / sendVideo / sendAudio 同构,仅接口路径不同。

cURL
# Step 1: 申请 S3 直传凭证
curl -X POST 'https://www.49chatapp.com/api/v1/bots/files/upload-credentials' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "fileName": "screenshot.png",
    "fileSize": 204800,
    "fileType": "image/png"
  }'
# => { "uploadUrl": "...", "key": "bots/xxx.png", "headers": {...} }

# Step 2: 使用返回的 uploadUrl / headers,客户端直传 S3
curl -X PUT "<uploadUrl>" -H 'Content-Type: image/png' --data-binary @screenshot.png

# Step 3: 登记上传结果,拿到 file_id
curl -X POST 'https://www.49chatapp.com/api/v1/bots/files/complete' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "key": "bots/xxx.png",
    "fileName": "screenshot.png",
    "fileSize": 204800,
    "fileType": "image/png"
  }'
# => { "file_id": "6530ab...f2", "url": "...", ... }

# Step 4: 发送图片消息(width / height 可选;不传时由 File 文档元数据自动补齐)
curl -X POST 'https://www.49chatapp.com/api/v1/bots/sendPhoto' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "chat_id": "6530ab...9c1",
    "file_id": "6530ab...f2",
    "caption": "部署成功截图",
    "width": 1920,
    "height": 1080
  }'

请求示例:editMessage / deleteMessage

仅限编辑 / 删除本机器人发送的消息,触发 edited_message / message_deleted Update。

cURL
# 编辑本机器人发送过的文本消息
curl -X POST 'https://www.49chatapp.com/api/v1/bots/editMessage' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "message_id": "6530ab12c9a0ff00123abc88",
    "text": "部署状态已更新:成功"
  }'

# 撤回一条自己发送的消息
curl -X POST 'https://www.49chatapp.com/api/v1/bots/deleteMessage' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{ "message_id": "6530ab12c9a0ff00123abc88" }'

请求示例:查看 Webhook 投递日志

使用账号 JWT 调用;用于排查投递失败与 dead_letter

cURL
# 开发者自助查看 Webhook 投递日志(需账号 JWT)
curl -G 'https://www.49chatapp.com/api/v1/bots/my/<bot_id>/deliveries' \
  -H 'Authorization: Bearer <jwt>' \
  --data-urlencode 'page=1' \
  --data-urlencode 'pageSize=20' \
  --data-urlencode 'status=dead_letter'
# => { "items": [ { "update_id": "...", "status": "dead_letter", "attempts": 5, "dead_letter_at": "...", "last_error": "..." } ], "total": 3 }

请求示例:setWebhook

建议填写 secret_token 便于验签;如果需要接收编辑 / 删除事件,请在 allowed_updates 显式声明。

cURL
curl -X POST 'https://www.49chatapp.com/api/v1/bots/setWebhook' \
  -H 'Authorization: Bearer sbot_<token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com/webhook/sochat",
    "secret_token": "replace-with-your-secret",
    "allowed_updates": [
      "message",
      "edited_message",
      "message_deleted",
      "message_read",
      "message_delivered",
      "callback_query",
      "inline_query",
      "friend_request",
      "my_chat_member",
      "chat_member",
      "chat_join_request"
    ],
    "allowed_ips": []
  }'

Webhook 与 Update

Update 由平台异步投递,不阻塞消息主链路。除 Webhook 之外,也可以用 getUpdates 长轮询拉取(与 Webhook 互斥,调用 setWebhook 自动切到 webhook 模式,调用 deleteWebhook 自动切回 polling 模式)。群聊默认 Privacy Mode 开启,仅推送命令、@机器人、回复机器人与服务类事件等。

支持的 Update 类型

setWebhook.allowed_updatesgetUpdates.allowed_updates 中显式声明可订阅类型;不传 / 传空数组等于全部。

type触发条件
message新消息:文本 / 图片 / 文件 / 视频 / 音频 / 语音 / 视频笔记 / 动图 / 贴纸 / 骰子 / 投票 / 联系人 / 位置 / 地点;具体子类型见 `message.file` / `message.location` 等字段。
edited_message由本机器人或被允许的客户端调用 `editMessage` 后触发;同条消息可多次编辑,仍按 `update_id` 区分。
message_deleted由本机器人或被允许的客户端调用 `deleteMessage` 后触发。
message_read对方已读机器人消息;仅在原消息发送者为本机器人时投递。须 `allowed_updates` 放行或缺省(默认已含)。
message_delivered消息已送达接收方设备;同样要求原消息发送者为本机器人。
callback_query用户点击 InlineKeyboard 按钮;5 秒内须调一次 `answerCallbackQuery`。
inline_query用户输入 `@botname <query>` 触发;需 `Bot.supports_inline_queries=true`,应答用 `answerInlineQuery`。
friend_request用户向机器人发起好友申请;需 `friend_request_mode=manual` 且订阅本类型。
my_chat_member本机器人自己在某会话内的角色 / 状态发生变化(入群、退群、被升降权等)。须显式订阅。
chat_member该会话其他成员的状态变化(角色升降、入群退群等);须显式订阅。
chat_join_request用户申请加入机器人所在的群(机器人需是管理员)。须显式订阅。

my_chat_member / chat_member / chat_join_request 默认投递,需要在 allowed_updates 中显式加入;其它类型在 setWebhook 缺省 allowed_updates 时默认已含。

  • 两种模式Webhook 主动推(设置 `setWebhook` 后 `Bot.delivery_mode=webhook`)或 polling 长轮询(`deleteWebhook` 后 `Bot.delivery_mode=polling`,调用 `getUpdates`);两者互斥,相同 Bot 同一时刻只允许一种。
  • 异步出站消息落库后由平台分发器匹配可见机器人并生成 Update:webhook 模式异步推送到你的端点;polling 模式则写入待拉取队列,等下一次 `getUpdates` 立即返回。
  • 群 Privacy Mode群聊仅投递:`/` 开头命令、文本含 `@username`、回复机器人消息、mentions 命中机器人 userId/username;私聊全部投递。
  • 稳定幂等键入站类 Update 的 `update_id = sha256(botId + messageId + updateType)`;平台重试保持同一 `update_id` 与 `X-StarIM-Update-Id`;客户侧以此去重。
  • 重试策略webhook 失败按固定节奏 1min / 5min / 15min / 1h 重试;首次 + 4 次重试共 5 次尝试,仍失败则落为 `dead_letter`(终态)。polling 模式由客户端 `offset` 推进 ack。
  • 签名摘要HMAC-SHA256(body, secret_token);若 `secret_token` 未配置,将投递失败(必须配置)。
  • 出站 IP调 `GET /bots/getWebhookInfo` 读 `platform_egress_ips`,便于客户在防火墙做白名单。
  • 载荷标识每条 Update 含 `bot_id` 与稳定 `update_id`;polling 模式额外带 `update_seq`,客户端用「上一批最后一条 + 1」做下次 `offset`。

请求头

平台 → 客户 Webhook 的固定请求头。

名称示例值说明
Content-Typeapplication/json始终 UTF-8 JSON 编码。
X-StarIM-Signaturesha256=<hex>HMAC-SHA256(raw_body, secret_token);请使用原始请求字节校验。
X-StarIM-Update-Id<uuid>与 payload.update_id 相同;作为幂等键。

平台要求客户端在 15 秒 内返回 2xx;否则视为失败并按固定节奏(1min / 5min / 15min / 1h)重试,首次加 4 次共 5 次尝试,仍失败则落为 dead_letter,可在控制台手动重投。

Privacy Mode 规则

群聊默认仅投递以下情形;私聊不做过滤。

场景是否投递说明
私聊全部投递机器人在私聊里可收到用户发送的全部消息。
群聊:`/` 命令投递如 `/deploy`、`/help`;空格前的 token 要以 `/` 开头。
群聊:`@username`投递文本中出现 `@<bot_username>`(大小写不敏感)。
群聊:回复机器人消息投递Quote / Reply 到机器人发送的消息上。
群聊:mentions 命中投递mentions 列表含机器人 `userId` 或 `username`。
群聊:其它普通消息不投递默认不会把群内普通聊天推给机器人。

Update 载荷示例(JSON)

下面依次展示常用 Update 类型:文本 / 图片 / 编辑 / 撤回 / 按钮点击 / Inline 查询 / 已读 / 群成员变化 / 好友申请。

JSON
// 1) 文本消息(type=message)
{
  "update_id": "3fb4e65c-4d6b-4b0d-9d9a-3a1b9c4f0e12",
  "type": "message",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "message": {
    "message_id": "6530ab12c9a0ff00123abc88",
    "from": { "id": "6530ab12c9a0ff00123ab801", "username": "alice", "is_bot": false },
    "chat": { "id": "6530ab12c9a0ff00123abc55", "type": "group", "title": "研发协作群" },
    "text": "/deploy status",
    "date": 1735689600
  }
}

// 2) 图片消息(type=photo;文件元数据在 message.file;width / height 等元数据若已知会一并带出)
{
  "update_id": "5ac9d1d4-3f9e-4a17-8dd6-7b0a1a3a8a01",
  "type": "photo",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "message": {
    "message_id": "6530ab12c9a0ff00123abc91",
    "from": { "id": "6530ab12c9a0ff00123ab801", "username": "alice", "is_bot": false },
    "chat": { "id": "6530ab12c9a0ff00123abc55", "type": "group", "title": "研发协作群" },
    "text": "看下这张截图 @bot",
    "file": {
      "file_id": "6530ab12c9a0ff00123abcf2",
      "file_name": "screenshot.png",
      "mime_type": "image/png",
      "file_size": 204800,
      "url": "https://s3.example.com/bots/6530.../screenshot.png",
      "thumbnail_url": "https://s3.example.com/bots/6530.../screenshot_thumb.png",
      "width": 1920,
      "height": 1080
    },
    "date": 1735692000
  }
}

// 3) 消息编辑(type=edited_message,由 editMessage 触发)
{
  "update_id": "7c33b8f2-7d24-4f4b-8a2c-1f4b2e0e10bd",
  "type": "edited_message",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "message": {
    "message_id": "6530ab12c9a0ff00123abc88",
    "chat": { "id": "6530ab12c9a0ff00123abc55" },
    "text": "/deploy status — 已更新",
    "date": 1735693500
  }
}

// 4) 消息撤回(type=message_deleted,由 deleteMessage 触发)
{
  "update_id": "91dd6d01-3c52-4c98-907e-6b8e8a01dd3a",
  "type": "message_deleted",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "message": {
    "message_id": "6530ab12c9a0ff00123abc88",
    "chat": { "id": "6530ab12c9a0ff00123abc55" },
    "date": 1735695000
  }
}

// 5) 按钮点击(type=callback_query,5 秒内须调 answerCallbackQuery)
{
  "update_id": "8b3a1c0c-12cd-4e08-9def-2a7c33b9bd44",
  "type": "callback_query",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "callback_query": {
    "id": "6530ab12c9a0ff00123abccb",
    "from": { "id": "6530ab12c9a0ff00123ab801", "username": "alice", "is_bot": false },
    "message": {
      "message_id": "6530ab12c9a0ff00123abc88",
      "chat": { "id": "6530ab12c9a0ff00123abc55", "type": "group" }
    },
    "data": "approve:order:123",
    "chat_instance": "6530ab12c9a0ff00123abc55"
  }
}

// 6) Inline 查询(type=inline_query,需 supports_inline_queries=true)
{
  "update_id": "2f6e6a51-c4ad-4d2f-bb6c-7f0e22115011",
  "type": "inline_query",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "inline_query": {
    "id": "6530ab12c9a0ff00123abcd0",
    "from": { "id": "6530ab12c9a0ff00123ab801", "username": "alice", "is_bot": false },
    "query": "天气 北京",
    "offset": "",
    "chat_type": "private"
  }
}

// 7) 已读 / 已送达(type=message_read / message_delivered,仅原消息发送者为本机器人时触发)
{
  "update_id": "a1d92c52-2e94-44b4-be17-44b3ff97b3a4",
  "type": "message_read",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "message": {
    "message_id": "6530ab12c9a0ff00123abc88",
    "chat": { "id": "6530ab12c9a0ff00123abc55", "type": "private" },
    "date": 1735695200
  }
}

// 8) 自己角色 / 群成员变化(须显式订阅 my_chat_member / chat_member / chat_join_request)
{
  "update_id": "c3e0a99a-3d5e-4f31-89e2-1c4b9c1d20a1",
  "type": "my_chat_member",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "my_chat_member": {
    "chat": { "id": "6530ab12c9a0ff00123abc55", "type": "group", "title": "研发协作群" },
    "from": { "id": "6530ab12c9a0ff00123ab8aa", "username": "owner", "is_bot": false },
    "date": 1735695300,
    "old_chat_member": { "user": { "id": "<bot_user_id>", "is_bot": true }, "status": "member" },
    "new_chat_member": { "user": { "id": "<bot_user_id>", "is_bot": true }, "status": "administrator" }
  }
}

// 9) 好友申请(type=friend_request,需 friend_request_mode=manual)
{
  "update_id": "9bcb1f24-0d4b-4c1f-8b40-aaa3a4f3a201",
  "type": "friend_request",
  "bot_id": "6530ab12c9a0ff00123abc01",
  "friend_request": {
    "id": "6530ab12c9a0ff00123abccc",
    "from": { "id": "6530ab12c9a0ff00123ab801", "username": "alice", "is_bot": false },
    "request_message": "我是 ACME 客服,麻烦通过",
    "source": "search",
    "date": 1735695500
  }
}

官方 SDK

SDK 把 Bot API、HMAC 验签、update_id 去重、命令路由打包成统一接口,几行代码即可完成消息收发与 Webhook 接入。 目前提供 Node.js / TypeScriptJava 两种语言。

Node.js · TypeScript已发布
Node ≥ 18

@starim-io/bot-sdk npm v0.1.6

ESM + CJS 双格式 / 自带类型声明 · 内置 Express/原生 HTTP 中间件 · fetch 原生实现,无运行时依赖。

Java已发布
JDK ≥ 17

io.starim:bot-sdk Maven v0.1.4

JDK 自带 HttpClient + jdk.httpserver · 仅依赖 Jackson Databind · 兼容 Spring Boot / Servlet / Micronaut。

两套官方 SDK 行为完全一致:Authorization: Bearer <bot_token> 调用 Bot API、X-StarIM-Signature HMAC-SHA256 验签、update_id LRU 去重、平台重试节奏 1m/5m/15m/1h。Python、Go 等其他语言暂不提供官方 SDK,如需请联系开放平台支持 / 客服。

1. 安装

Node 18+;ESM/CJS 双格式发布。

bash
# 任选包管理器
npm install @starim-io/bot-sdk
pnpm add @starim-io/bot-sdk
yarn add @starim-io/bot-sdk

2. 快速开始:Echo Bot

高阶 StarIMBot 内置 HTTP 服务、验签、命令路由与去重,几行代码上线。

TypeScript
import { StarIMBot } from '@starim-io/bot-sdk'

const bot = new StarIMBot({
  token: process.env.STARIM_BOT_TOKEN!,
  secretToken: process.env.STARIM_WEBHOOK_SECRET!,
  baseUrl: process.env.STARIM_API_BASE, // 例: https://api.example.com/v1
})

// 命令路由:当用户发送 /start 时回复
bot.command('start', (ctx) => ctx.reply('你好,我是 49热聊 机器人 👋'))

// 通用消息:回声
bot.on('message', async (ctx) => {
  if (ctx.message.text) {
    await ctx.reply('你说: ' + ctx.message.text)
  }
})

// 启动内置 HTTP 服务(自动验签 / 去重 / 路由分发)
await bot.start({ port: 8787, path: '/webhook' })
console.log('Bot is up on :8787/webhook')

将公网 HTTPS 反代到 http://<host>:8787/webhook,在开发者控制台把 Webhook URL 设为反代后的 https://你的域名/webhook

3. 仅调用 API:低阶客户端

不接 Webhook、只主动推送时使用 StarIMBotClient

TypeScript
import { StarIMBotClient } from '@starim-io/bot-sdk'

const client = new StarIMBotClient({
  token: process.env.STARIM_BOT_TOKEN!,
  baseUrl: process.env.STARIM_API_BASE,
})

// 配置 Webhook
await client.setWebhook({
  url: 'https://example.com/webhook',
  secret_token: 'your-secret',
  allowed_updates: ['message'],
})

// 主动推送
const me = await client.getMe()
await client.sendMessage({
  chat_id: '<conversationId>',
  text: '系统通知:今晚 22:00 例行维护',
})

// 编辑、撤回(仅本机器人发送的消息)
const sent = await client.sendMessage({ chat_id, text: '加载中…' })
await client.editMessage({ chat_id, message_id: sent.message_id, text: '已完成 ✅' })
await client.deleteMessage({ chat_id, message_id: sent.message_id })

4. 与 Express 集成

  • bot.webhookCallback() 返回 Express 兼容中间件,自动验签、去重、分发事件。
  • 务必使用 express.raw({ type: 'application/json' }),否则原始字节被丢弃,签名无法对齐。
TypeScript
import express from 'express'
import { StarIMBot } from '@starim-io/bot-sdk'

const app = express()

const bot = new StarIMBot({
  token: process.env.STARIM_BOT_TOKEN!,
  secretToken: process.env.STARIM_WEBHOOK_SECRET!,
})

bot.on('message', async (ctx) => {
  if (ctx.message.text === 'ping') await ctx.reply('pong')
})

// 关键:用 express.raw 保留原始字节用于 HMAC 验签
app.post(
  '/webhook',
  express.raw({ type: 'application/json' }),
  bot.webhookCallback(),
)

// 其他路由可以照常使用 express.json()
app.use(express.json())
app.get('/health', (_req, res) => res.json({ ok: true }))

app.listen(8787)

5. 多媒体一步法

SDK 自动完成 申请凭证 → S3 直传 → complete 登记 → sendPhoto/sendDocument,开发者只需提供本地路径或 Buffer。

TypeScript
import { StarIMBotClient, sendPhotoFromBuffer, sendPhotoFromUrl } from '@starim-io/bot-sdk'
import { readFile } from 'node:fs/promises'

const client = new StarIMBotClient({
  token: process.env.STARIM_BOT_TOKEN!,
  baseUrl: process.env.STARIM_API_BASE,
})

// 1) 本地路径(最常见)
await client.sendPhotoFromFile(chatId, './chart.png', { caption: '今日 PV 趋势' })

// 2) 内存 Buffer
const buf = await readFile('./chart.png')
await sendPhotoFromBuffer(client, chatId, buf, {
  fileName: 'chart.png',
  fileType: 'image/png',
})

// 3) 远端 URL(SDK 帮你下载 → 上传 → 发送)
await sendPhotoFromUrl(client, chatId, 'https://cdn.example.com/p.png', {
  fileName: 'p.png',
})

6. 错误处理

API 错误统一抛 StarIMApiError;签名错误抛 StarIMSignatureError,对应返回 401

TypeScript
import { StarIMApiError, StarIMSignatureError } from '@starim-io/bot-sdk'

try {
  await client.sendMessage({ chat_id, text: 'hello' })
} catch (err) {
  if (err instanceof StarIMApiError) {
    // err.statusCode / err.code / err.message
    if (err.statusCode === 429) {
      // 触发配额,按 Retry-After 延后再试
    }
    if (err.code === 'invalid_token') {
      // Token 失效:刷新 / 重新申请
    }
  }
  throw err
}

// Webhook 中:自定义中间件捕获签名错误
try {
  await bot.processWebhook(rawBody, signatureHeader, updateIdHeader)
} catch (err) {
  if (err instanceof StarIMSignatureError) {
    return res.status(401).end()
  }
  throw err
}

主要方法对照

两套 SDK 命名风格保持一致;返回值字段以 Bot API 为准。

能力Node.jsJava其他语言Bot API 端点
获取自身 / 校验 Tokenclient.getMe() · client.verifyToken()client.getMe() · client.verifyToken()按 HTTP API 接入 / 联系客服GET /bots/me
发送文本client.sendMessage({chat_id,text})client.sendMessage(chatId, text)按 HTTP API 接入 / 联系客服POST /bots/sendMessage
发送图片 / 文件 / 视频 / 音频client.sendPhoto / sendDocument / sendVideo / sendAudioclient.sendPhoto / sendDocument / sendVideo / sendAudio按 HTTP API 接入 / 联系客服POST /bots/send{Photo|Document|Video|Audio}
富消息:voice / videoNote / animation / stickerclient.sendVoice / sendVideoNote / sendAnimation / sendStickerclient.sendVoice / sendVideoNote / sendAnimation / sendSticker按 HTTP API 接入 / 联系客服POST /bots/send{Voice|VideoNote|Animation|Sticker}
骰子 / 投票 / 联系人 / 地点 / 媒体组client.sendDice · sendPoll · sendContact · sendVenue · sendMediaGroupclient.sendDice · sendPoll · sendContact · sendVenue · sendMediaGroup按 HTTP API 接入 / 联系客服POST /bots/send{Dice|Poll|Contact|Venue|MediaGroup}
发送位置client.sendLocationclient.sendLocation按 HTTP API 接入 / 联系客服POST /bots/sendLocation
编辑 / 撤回 / 转发client.editMessage · deleteMessage · forwardMessage · copyMessageclient.editMessage · deleteMessage · forwardMessage · copyMessage按 HTTP API 接入 / 联系客服POST /bots/{editMessage|deleteMessage|forwardMessage|copyMessage}
InlineKeyboard 编辑 / 应答client.editMessageReplyMarkup · client.answerCallbackQueryclient.editMessageReplyMarkup · client.answerCallbackQuery按 HTTP API 接入 / 联系客服POST /bots/{editMessageReplyMarkup|answerCallbackQuery}
Inline Mode 应答client.answerInlineQueryclient.answerInlineQuery按 HTTP API 接入 / 联系客服POST /bots/answerInlineQuery
命令菜单client.setMyCommands / getMyCommands / deleteMyCommandsclient.setMyCommands / getMyCommands / deleteMyCommands按 HTTP API 接入 / 联系客服POST /bots/{set|get|delete}MyCommands
Webhook 配置 / 摘要client.setWebhook · deleteWebhook · getWebhookInfoclient.setWebhook · deleteWebhook · getWebhookInfo按 HTTP API 接入 / 联系客服POST/GET /bots/{setWebhook|deleteWebhook|getWebhookInfo}
长轮询拉取client.getUpdates({offset,timeout}) · bot.startPolling()client.getUpdates(GetUpdatesParams) · bot.startPolling(timeoutSec)按 HTTP API 接入 / 联系客服POST /bots/getUpdates
资料管理client.setMyShortDescription / setMyDescription / getMyShortDescription / getMyDescriptionclient.setMyShortDescription / setMyDescription / getMyShortDescription / getMyDescription按 HTTP API 接入 / 联系客服POST /bots/{set|get}My{Short,}Description
群读取client.getChat / getChatMember / getChatMemberCount / getChatAdministratorsclient.getChat / getChatMember / getChatMemberCount / getChatAdministrators按 HTTP API 接入 / 联系客服GET /bots/getChat*
群信息修改 / 置顶client.setChatTitle / setChatDescription / setChatPhoto · pinChatMessage 系client.setChatTitle / setChatDescription / setChatPhoto · pinChatMessage 系按 HTTP API 接入 / 联系客服POST /bots/{setChat*|pin*}
群治理 / chatActionclient.kickChatMember · banChatMember · unbanChatMember · sendChatActionclient.kickChatMember · banChatMember · unbanChatMember · sendChatAction按 HTTP API 接入 / 联系客服POST /bots/{kick|ban|unban}ChatMember · POST /bots/sendChatAction
好友申请 manualclient.getFriendRequests · answerFriendRequest · set/getMyFriendRequestModeclient.getFriendRequests · answerFriendRequest · set/getMyFriendRequestMode按 HTTP API 接入 / 联系客服POST/GET /bots/*FriendRequest*
投递日志 & 重投— (开发者控制台)— (开发者控制台)按 HTTP API 接入 / 联系客服GET /bots/my/:id/deliveries(账号 JWT,非 Bot Token)
S3 上传两步 / getFileclient.issueUploadCredentials · completeUpload · getFileclient.issueUploadCredentials · completeUpload · getFile按 HTTP API 接入 / 联系客服POST/GET /bots/{files/...|getFile}
本地一步上传并发送client.sendPhotoFromFile · sendPhotoFromBuffer · sendPhotoFromUrlclient.sendPhotoFromFile · sendDocumentFromFile · uploadFile按 HTTP API 接入 / 联系客服SDK 封装能力
高阶事件路由new StarIMBot(...) · bot.on() · bot.command() · bot.start()StarIMBot.builder() · bot.on() · bot.command() · bot.start()按 HTTP API 接入 / 联系客服内置 Webhook server / 框架解耦

完整 API 列表与高级用法(自定义去重、allowed_updates 过滤、长轮询的 offset/timeout 调优、`reply_markup` 透传等)请参考 Node / Java SDK 文档。投递日志查询与重试可通过开发者控制台完成;其他语言请按 Bot API HTTP 契约接入,或联系开放平台支持。

没有公网 IP?用 long-poll

长轮询

在本机起 bot 没有 HTTPS 也没问题。先 deleteWebhook 切到 polling 模式,再用 SDK 的 startPolling(),完整支持 offset / timeout / allowed_updates 等参数;平台层会做多实例去重与即时唤醒,长轮询体感与 webhook 几乎无差,但完全免去公网门槛。

// Node SDK
import { StarIMBot } from '@starim-io/bot-sdk';

const bot = new StarIMBot({
  token: process.env.STARIM_BOT_TOKEN!,
  baseUrl: 'https://your-api-host/api/v1',
  secretToken: 'unused-in-polling-mode'
});
bot.command('start', ctx => ctx.reply('hi from polling bot'));

await bot.client.deleteWebhook();   // 切到 polling 模式
await bot.startPolling({ timeout: 30 });
// Java SDK
StarIMBot bot = StarIMBot.builder()
        .token(System.getenv("STARIM_BOT_TOKEN"))
        .secretToken("unused-in-polling-mode")
        .baseUrl("https://your-api-host/api/v1")
        .build();
bot.command("start", ctx -> ctx.reply("hi from polling bot"));

bot.getClient().deleteWebhook();
new Thread(() -> bot.startPolling(30)).start();
  • setWebhookgetUpdates 互斥:webhook 模式下调 getUpdates409 Conflict,避免双通道同时消费同一条 Update。
  • SDK 自带 LRU 去重 + 指数退避(2/4/8/.../30s),客户端代码无需额外处理网络抖动。
  • 平台横向扩容到多实例时不会重复投递(仍享受「至多一次」承诺)。

公共字段速查

贯穿 Bot API 与 Update 载荷的高频字段含义;其中 chat_id 即 49热聊 中的会话标识。

字段含义说明
bot_id机器人实例 ID24 位字符串 ID;与系统账号 `system_user_id` 一对一。
chat_id会话标识与平台内 `conversationId` 同源,私聊、群聊同一口径。
message_id平台消息 ID站内消息 ID;`sendMessage` / `editMessage` / `deleteMessage` 均使用该字段。
update_idUpdate 唯一 ID入站类 `message / photo / ...` 由 `sha256(botId + messageId + updateType)` 派生(多实例平台只投递一次);`edited_message` / `message_deleted` 等仍用 UUID。重试保持不变。
update_seqpolling 自增序号仅 `getUpdates` 返回;客户端以「上一批最后一条 + 1」作为下次 `offset` 实现 ack。
system_user_id机器人系统账号审核通过后由平台自动创建,机器人在会话中以该账号身份发言。
delivery_mode投递模式`webhook` / `polling`,`setWebhook` / `deleteWebhook` 会自动切换;webhook 模式下调 `getUpdates` 返回 409。
file_id机器人文件 ID由 `/files/complete` 或 `/getFile` 返回,多媒体接口均使用该字段。
file.width / height图片 / 视频尺寸像素;`sendPhoto` / `sendVideo` / `sendVideoNote` / `sendAnimation` / `sendSticker` 可选,或由 File 文档 `metadata.dimensions` 自动补齐。
file.duration音视频时长秒;`sendAudio` / `sendVideo` / `sendVoice` / `sendVideoNote` / `sendAnimation` 可选,或由 File 文档 `metadata.duration` 自动补齐。
file.performer / title音乐元信息`sendAudio` / `sendVoice` 可选;适合音乐 / 播客;Webhook Update 载荷同步带出。
metadata.diceEmoji / diceValue骰子点数`sendDice` 服务端掷点结果;🎰 1–64,⚽/🏀 1–5,其余默认 1–6。
metadata.poll投票结构`sendPoll` 写入 `{ question, options, is_anonymous, type, correct_option_id? }`。
metadata.contact联系人卡片`sendContact` 写入 `{ phone_number, first_name, last_name }`。
metadata.isVenue是否地点`sendVenue` 写入 `true`,与 `sendLocation` 公用 `latitude` / `longitude` / `name` / `address`。
rate_limits机器人级速率配额`send_per_sec / send_per_min / send_per_day`;未设置则回退到全局默认。
metadata.isEdited编辑标记`editMessage` 成功后写入;客户端据此显示"已编辑"标签。
pinned_message_id会话置顶通过 `pinChatMessage` / `unpinChatMessage` 维护,`getChat` 响应一并返回。
platform_egress_ips平台出站 IP由 `getWebhookInfo` 返回,便于在你的防火墙做出站白名单。
dead_letter_at投递死信时间5 次尝试均失败后落为 `dead_letter`,该字段记录时间点;可在控制台手动重投。

字段命名遵循 snake_case;版本升级如有改动会在版本日志中标注。

错误码

所有失败响应统一返回 { success: false, code, message },HTTP 状态与 code 一一对应。下表列出最常见的业务错误,遇到未列出的错误请参照 message 与 HTTP 状态码处理。

code典型 HTTP说明处理建议
BOT_TOKEN_REQUIRED401请求缺少 `Authorization: Bearer <token>`检查请求头或请求体 `token` 字段。
INVALID_BOT_TOKEN401Token 不存在、已被吊销或与 Bot 不匹配确认 Token 未轮换 / 吊销;使用最新一次签发的明文值。
BOT_NOT_AVAILABLE403机器人未审核通过或已停用 (`review_status != approved` 或 `status != enabled`)在「开发者控制台」查看审核状态;被停用时请联系开放平台支持。
VALIDATION400参数不合法,如 `chat_id` / `text` 缺失、Webhook URL 非 HTTPS、`file_id` 缺失、`options` 数量不在 2..12 等按接口字段要求补齐;URL 必须以 `https://` 开头。
FORBIDDEN403仅限编辑 / 删除本机器人(同一 `system_user_id`)发送的消息;或群治理类未授予机器人群主 / 管理员确认 `message_id` 属于当前机器人发送的消息;或先将机器人提升为群主 / 管理员。
CONFLICT409当前为 `webhook` 模式时调 `getUpdates`,或同一 `callback_query_id` 重复 `answerCallbackQuery`webhook 模式下要先调 `deleteWebhook` 才能用 `getUpdates`;按钮回调只能 answer 一次。
NOT_FOUND404`chat_id` / `message_id` / `file_id` 等资源不存在检查传入的 ID 与机器人当前可见会话。
RATE_LIMITED429触发平台路由级速率限制按 `Retry-After` 退避重试;具体配额以接入文档为准。
BOT_RATE_LIMIT429触发机器人级发送配额(`send_per_sec / send_per_min / send_per_day`,叠加全局默认)读取响应头 `Retry-After` 与 `X-BotRateLimit-Remaining`;如长期受限,请联系开放平台支持调整阈值。
WEBHOOK_DELIVER_FAILED投递日志中的终态;首次加 4 次重试(1min / 5min / 15min / 1h)共 5 次仍失败后落为 `dead_letter`检查你服务端的 2xx 响应、15 秒超时与 HMAC 验签实现;失败记录可在「开发者控制台」的投递日志中手动重投。

企业级特性总览

面向企业接入场景设计的能力一览,覆盖准入、消息、群治理、配额与监控。

维度能力说明
准入与审核开发者在「开发者控制台」提交创建申请,开放平台审核通过后签发 Bot Token;申请、审批、变更与吊销全程留痕,可在控制台查阅。
消息类型覆盖 text / photo / document / video / audio / voice / video_note / animation / sticker / dice / poll / contact / location / venue / media_group。
群治理getChat 系 / setChat 系 / pinChat 系、forwardMessage / copyMessage / sendChatAction / getFile 等读写端点;写类操作需机器人为群主或群管理员。
交互能力`callback_query` + `answerCallbackQuery`、`inline_query` + `answerInlineQuery`、`setMyCommands` 命令菜单。
投递模式Webhook 与 Polling 互斥,`setWebhook` / `deleteWebhook` 自动维护 `Bot.delivery_mode`;调用顺序错误返回 `409 Conflict`。
群成员事件`my_chat_member` / `chat_member` / `chat_join_request`,需在 `allowed_updates` 中显式订阅。
已读 / 已送达`message_read` / `message_delivered`,仅当原消息发送者为本机器人时投递。
速率配额全局默认 + 机器人级配额(`send_per_sec` / `send_per_min` / `send_per_day`);超限返回 `429 BOT_RATE_LIMIT` 与 `Retry-After`。
监控与排障可在「开发者控制台」查看近 24h 投递与 API 调用指标,Webhook 投递日志按状态分页,失败 / dead_letter 支持手动重投。
出站 IP`GET /bots/getWebhookInfo` 返回 `platform_egress_ips`,便于在你的防火墙做出站白名单。

验签与 Webhook 示例(Node.js)

HMAC-SHA256 验签、Update 幂等去重与 Echo Bot 的最小实现;签名以 setWebhook 提交的 secret_token 为密钥,对原始请求字节计算。

HMAC 验签

使用原始 body 字节;timingSafeEqual 防时序攻击。

JavaScript
import crypto from 'node:crypto'

/**
 * @param rawBody - 与平台计算签名时一致的原始字节
 * @param signatureHeader - 如 X-StarIM-Signature: sha256=...
 * @param secret - setWebhook 时配置的 secret_token
 */
export function verifyWebhookSignature(rawBody, signatureHeader, secret) {
  if (!signatureHeader || !secret) return false
  const body = typeof rawBody === 'string' ? Buffer.from(rawBody) : rawBody
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(body).digest('hex')
  const a = Buffer.from(expected)
  const b = Buffer.from(String(signatureHeader).trim())
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

幂等去重

  • update_id 作幂等键;平台重试时不变。
  • 同一条用户消息无论平台调度多少次都只会触发一次入站投递message / photo / document / video / audio / location)。
  • edited_message / message_deleted 同一条消息可能多次发生,仍按事件本身去重,请用 update_id
  • Webhook 尽快返回 2xx;重活放异步。
JavaScript
const seen = new Set() // 生产环境请换 Redis / DB

function isDuplicateUpdate(updateId) {
  if (seen.has(updateId)) return true
  seen.add(updateId)
  return false
}

Echo Bot(Express)

验签后解析 Update,回发 sendMessage

JavaScript
// POST /webhook — 验签通过后解析 Update,Echo 文本消息
app.post('/webhook/sochat', express.raw({ type: '*/*' }), async (req, res) => {
  const raw = req.body
  const sig = req.get('X-StarIM-Signature') || ''
  if (!verifyWebhookSignature(raw, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).end()
  }
  const update = JSON.parse(raw.toString('utf8'))
  if (isDuplicateUpdate(update.update_id)) {
    return res.status(200).json({ ok: true })
  }
  const text = update.message?.text
  const chatId = update.message?.chat?.id
  if (update.type === 'message' && text && chatId) {
    await fetch('https://www.49chatapp.com/api/v1/bots/sendMessage', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.BOT_TOKEN,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ chat_id: chatId, text }),
    })
  }
  res.status(200).json({ ok: true })
})

安全与合规

Bot Token 与用户 JWT 分离;平台审核;日志与投递脱敏、可审计。

鉴权隔离

  • Bot Token 与用户 JWT 完全隔离
  • 由平台层负责 Token 校验
  • 业务侧仅接收已解析的 `bot_id` 等上下文

Webhook 安全

  • 默认要求 HTTPS
  • 支持 HMAC 签名头
  • 可扩展 IP 白名单与时间窗校验
  • 首次 + 4 次重试后落 `dead_letter`

Token 治理

  • 审核通过前不生成 Token
  • 首次明文仅展示一次
  • 轮换后旧 Token 立即失效

速率配额

  • 全局默认 + Bot 级配额
  • 按秒 / 按分钟 / 按日 三个时间窗
  • 超限返回 `BOT_RATE_LIMIT` + `Retry-After`
  • 平台可按机器人调整阈值

审计与脱敏

  • 审核、吊销、停用、配额变更全部记录可追溯
  • 触发速率配额会被记录用于回溯与配额评估
  • 日志中只暴露 Token 前缀与域名,明文不会落盘
  • 异常调用与失败投递可订阅告警

可观测性

  • 平台暴露 `/metrics` Prometheus 指标
  • 监控 API 调用量、投递成功率、队列积压、限流命中
  • 近 24h 监控看板,便于快速排障

版本日志

按发布顺序记录已上线的能力与不兼容调整。本接入文档对应 API 版本 v1; 未来如有破坏性变更,会在新版本路径下以新版本号发布,并在本日志列出迁移建议。

  1. 2026-05

    富消息 + 群治理 + 回执事件

    • ·消息:sendVoice / sendVideoNote / sendAnimation / sendSticker / sendDice / sendPoll / sendContact / sendVenue / sendMediaGroup
    • ·群:getChat / getChatMember / getChatMemberCount / getChatAdministrators
    • ·群:setChatTitle / setChatDescription / setChatPhoto;pinChatMessage / unpinChatMessage / unpinAllChatMessages
    • ·群:forwardMessage / copyMessage / sendChatAction / getFile / kickChatMember / banChatMember / unbanChatMember
    • ·事件:message_read / message_delivered(默认订阅,须保持 allowed_updates 放行)
    • ·事件:my_chat_member / chat_member / chat_join_request(需在 allowed_updates 显式订阅)
    • ·getWebhookInfo 返回 platform_egress_ips,便于在防火墙做白名单
  2. 2026-04

    好友申请审核 & 群成员调度(增值能力)

    • ·好友申请:friend_request_mode + getFriendRequests / answerFriendRequest + friend_request 事件
    • ·调度成员(增值,默认未开放):listChatVirtualMembers / simulateSendMessage;调用全程记录用于合规追溯
  3. 2026-03

    Inline Mode

    • ·应答用户在输入框中触发的 inline 查询:inline_query 事件 + answerInlineQuery
    • ·需将 Bot.supports_inline_queries 置为 true,并在 allowed_updates 含 inline_query
  4. 2026-02

    InlineKeyboard 编辑接口对齐

    • ·editMessageReplyMarkup:仅编辑按钮,不改正文,传 null 等价清空
  5. 2026-02

    机器人资料字段补全

    • ·setMyShortDescription / getMyShortDescription(≤120 字符短介绍)
    • ·setMyDescription / getMyDescription(≤512 字符长介绍)
    • ·资料 cover / links / contact 等结构化字段开放
  6. 2026-01

    长轮询接入

    • ·POST /bots/getUpdates(与 Webhook 互斥,自动维护 delivery_mode)
    • ·Node / Java SDK 提供 startPolling(),自动处理 offset 推进、退避与去重
    • ·没有公网 IP 也能起 bot
  7. 2025-12

    交互能力开放

    • ·InlineKeyboard 按钮 + callback_query 事件 + answerCallbackQuery(5s 内必须应答)
    • ·命令菜单:setMyCommands / getMyCommands / deleteMyCommands,按 scope / language_code 分组
  8. 2025-11

    消息能力增强

    • ·多媒体:sendPhoto / sendDocument / sendVideo / sendAudio / sendLocation
    • ·editMessage / deleteMessage(仅作用于本机器人发出的消息)+ edited_message / message_deleted 事件
    • ·机器人级速率配额(send_per_sec / send_per_min / send_per_day)
    • ·投递日志可分页查询,dead_letter 可手动重投
  9. 2025-09

    最小可上线闭环

    • ·机器人申请与审核,明文 Token 仅首次返回;Token 哈希存储、可吊销可重签
    • ·setWebhook + HMAC-SHA256 签名,固定节奏 1m / 5m / 15m / 1h 重试,5 次后落为 dead_letter
    • ·sendMessage 文本消息发送闭环

常见问题

为什么不是申请后立即拿到 Token?
49热聊 面向企业与私有化场景,需要平台在准入、责任归属和滥用风险上做统一审核,因此 Token 只有在审核通过后才会签发。
Webhook 为什么必须异步投递?
Webhook 属于出站 HTTP 调用,网络波动、超时与客户侧限流都很常见。异步队列可以避免阻塞消息主链路,并支持重试、死信和并发控制。
群里所有消息都会推给机器人吗?
不会。默认群隐私模式开启,只推送命令、@机器人、回复机器人消息以及服务事件(如 edited_message / message_deleted),避免机器人获取不必要的群聊内容。
现在开放平台能做哪些典型场景?
常见落地场景包括:审批与监控告警(文本 + 图片 + 文件 + 动图 + 贴纸)、智能助手(支持编辑与撤回自己的回答)、客服机器人(Inline 按钮回调 + Inline Mode)、随机互动(dice / poll)、群运营(群名 / 群描述 / 置顶 / 踢人 / 拉黑 / sendChatAction)、好友申请审核(manual)、位置 / 地点打卡、媒体组日报、知识库问答等。
没有公网 IP 也能起 bot 吗?
可以。先调 `POST /api/v1/bots/deleteWebhook` 把机器人切到 `polling` 模式,再用 `POST /api/v1/bots/getUpdates` 长轮询拉取即可;Node / Java SDK 提供 `startPolling()` 自动处理 `offset` / 退避 / 去重。webhook 模式下调用 `getUpdates` 会返回 409 Conflict。
callback_query / answerCallbackQuery 怎么用?
在 `sendMessage` 时附 `reply_markup: { inline_keyboard: [[{ text, callback_data }]] }`;用户点击后平台投递 `callback_query` Update,Bot 必须在 5 秒内调一次 `answerCallbackQuery`(同一 `callback_query_id` 重复 410),可选携带 `text` / `show_alert` / `url`,App 端会显示 toast / alert / 外链。
怎么订阅群成员变化、好友申请等事件?
默认 `setWebhook` 不传 `allowed_updates` 时已含 `message / edited_message / message_deleted / message_read / message_delivered / callback_query / inline_query / friend_request`;`my_chat_member` / `chat_member` / `chat_join_request` 须在 `allowed_updates` 中显式声明。好友申请还需把 `friend_request_mode` 改为 `manual`。
如何发送图片、文件等多媒体?
分两步:先调用 POST /api/v1/bots/files/upload-credentials 获取 S3 直传凭证,客户端直接 PUT 到 S3;上传完成后调用 POST /api/v1/bots/files/complete 登记,拿到 file_id,再调用 sendPhoto / sendDocument / sendVideo / sendAudio,对应参数填 file_id 即可。
editMessage / deleteMessage 有什么限制?
只能编辑或删除「由本机器人发送(同 system_user_id)」的消息,其他消息返回 403 FORBIDDEN;editMessage 目前仅支持文本替换。编辑 / 删除成功后会对所有订阅了 edited_message / message_deleted 的 Webhook 触发 Update。
收到 429 / BOT_RATE_LIMIT 怎么办?
配额为全局默认 + Bot 级覆盖(可选)。超限返回 HTTP 429,携带 Retry-After 与 X-BotRateLimit-Remaining 头,请按 Retry-After 退避。若业务长期超限,请联系平台支持调整该 Bot 的发送阈值。
Webhook 签名怎么算的?
平台以 setWebhook 时的 secret_token 为密钥,对即将发送的 JSON 请求体做 HMAC-SHA256,十六进制值写入 X-StarIM-Signature: sha256=<hex>。客户端请使用原始请求字节验签,避免 JSON 再序列化导致字节不一致。若未配置 secret_token,投递会失败(请在 setWebhook 中务必提供密钥)。
Webhook 失败会怎么重试?
平台要求在 15 秒内返回 2xx 才视为成功,否则按固定节奏 1min / 5min / 15min / 1h 做 4 次退避,首次加起来共 5 次尝试;仍失败则落为 dead_letter。所有重试保持同一 update_id;开发者可在本站「开发者控制台 / 投递日志」或调用 GET /api/v1/bots/my/:id/deliveries 查看详情,平台支持也可协助重投。
Bot Token 忘记保存了怎么办?
审核通过后只有第一次进入「开发者控制台 → 机器人详情」时会返回 `one_time_token`,读取后立即销毁。如果遗失,可在「开发者控制台」对该机器人执行「重新生成 Token」,平台会签发新的明文 Token 并立即吊销旧 Token;正在使用旧 Token 的进程会收到 401,请尽快切换。

下一步

完成申请与审核后,可用 Echo Bot 跑通 sendMessage 与 Webhook 闭环。遇到问题可通过支持渠道联系。