上手
1. Token
在 App 内创建机器人后,记下 bot_token,每个请求都要带在 Header 里(见下一节)。
2. 先上传媒体(可选)
发图、视频、音频前,一般需要先上传文件,响应里会有 file_id,发消息时带上即可。
curl -X POST "https://api.bi.ink/bot/uploadfile" \ -H "Authorization: Bearer YOUR_BOT_TOKEN" \ -F "file=@/path/to/image.jpg"
3. 发一条文字
curl -X POST "https://api.bi.ink/bot/sendmessage" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"group_id": "group_123",
"message_type": "text",
"content": "Hello, World!"
}'
群聊用 group_id;私聊用 target_user_id,二选一。
请求头
所有机器人接口都要求在 Header 里携带:
Authorization: Bearer YOUR_BOT_TOKEN
消息类型
message_type 取值与 JSON 骨架如下(group_id / target_user_id 按会话类型选一个)。
文本 text
纯文字。
{
"group_id": "group_123",
"message_type": "text",
"content": "这是一条文本消息"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 text |
是 |
content |
string | 正文 | 是 |
图片 image
JPG / PNG / GIF 等,需先有 file_id。
{
"group_id": "group_123",
"message_type": "image",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 image |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
视频 video
如 MP4、MOV。
{
"group_id": "group_123",
"message_type": "video",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 video |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
音频 audio
如 MP3、WAV、M4A。
{
"group_id": "group_123",
"message_type": "audio",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 audio |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
文件 file
任意附件类型。
{
"group_id": "group_123",
"message_type": "file",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 file |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
贴纸 sticker
传 file_id 即可,服务端会解析资源。
{
"group_id": "group_123",
"message_type": "sticker",
"file_id": "sticker_123456"
}
联系人 contact
分享名片,file_id 此处为用户相关标识(与业务约定一致)。
{
"group_id": "group_123",
"message_type": "contact",
"file_id": "user_123456"
}
按钮与回复
内联键盘
发消息时在 extra.inline_keyboard 里放二维数组,每项为 text + callback_data。
{
"group_id": "group_123",
"message_type": "text",
"content": "请选择:",
"extra": {
"inline_keyboard": [
[
{"text": "确认", "callback_data": "confirm"},
{"text": "取消", "callback_data": "cancel"}
],
[
{"text": "查看详情", "callback_data": "detail"}
]
]
}
}
回调怎么处理
- 用户点了按钮,你的 Webhook 会收到
event_type为callback_query的 JSON。 - 里面会有
callback_id(形如cb_userId_xxx)、callback_data、原消息message_id、点击人sender_id。 - 在约 30 秒内请求
POST /bot/answercallback,把callback_id回给服务端;需要的话再调editmessage改文案或清掉键盘。
Webhook 回调示例
{
"event_type": "callback_query",
"message_id": "msg_abc123",
"sender_id": "user_xxx",
"sender_username": "john",
"sender_display_name": "John Doe",
"group_id": "group_123",
"group_title": "测试群组",
"message_type": "callback",
"content": "confirm",
"timestamp": 1732636800,
"callback_id": "cb_user123_abc12345",
"callback_data": "confirm"
}
应答回调
curl -X POST "https://api.bi.ink/bot/answercallback" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"callback_id": "cb_user123_abc12345",
"text": "操作成功",
"show_alert": false
}'
text:提示文案;show_alert 为 true 时用弹窗,否则多为轻提示;url 可选,给按钮跳转用。
回复某条消息
{
"group_id": "group_123",
"message_type": "text",
"content": "回复内容",
"reply_to_id": "msg_123456"
}
引用消息
{
"group_id": "group_123",
"message_type": "text",
"content": "引用回复",
"quote_message_id": "msg_123455"
}
Webhook
在机器人后台配置 URL 后,用户发消息、点按钮、有人进群等事件会以 POST JSON 推到你的地址。下面列常见 event_type。
| event_type | 含义 | 大致时机 |
|---|---|---|
private_message |
私聊 | 用户私聊机器人 |
group_message |
群聊 | 群内 @ 机器人或命令等(以产品规则为准) |
member_joined |
新成员入群 | 机器人所在群有新成员 |
callback_query |
按钮 | 用户点击内联按钮 |
私聊示例
{
"event_type": "private_message",
"message_id": "msg_abc123",
"sender_id": "user_xxx",
"sender_username": "john",
"sender_display_name": "John Doe",
"group_id": "",
"group_username": "",
"group_title": "",
"message_type": "text",
"content": "你好",
"timestamp": 1732636800,
"callback_id": "",
"callback_data": ""
}
接口列表
上传文件
POST /bot/uploadfile,multipart 字段名 file。成功返回里带 file_id。
curl -X POST "https://api.bi.ink/bot/uploadfile" \ -H "Authorization: Bearer YOUR_BOT_TOKEN" \ -F "file=@/path/to/file.jpg"
{
"code": 200,
"msg": "文件上传成功",
"data": {
"file_id": "file_123456"
}
}
发消息
POST /bot/sendmessage。媒体类只传 file_id 即可。
编辑消息
POST /bot/editmessage
{
"message_id": "msg_xxx",
"content": "已更新",
"extra": {
"inline_keyboard": []
}
}
删消息
POST /bot/deletemessage。单条:
{ "message_id": "msg_xxx" }
多条:
{ "message_ids": ["msg_123", "msg_456", "msg_789"] }
群里通常要有管理权限或机器人被授予相应能力;私聊里参与者规则以客户端为准。
当前机器人信息
POST /bot/getme
群资料
POST /bot/getgroup,不含群主等敏感字段。
应答按钮
POST /bot/answercallback,收到 callback_query 后尽快调用。
{
"callback_id": "cb_user123_abc12345",
"text": "操作成功",
"show_alert": false,
"url": ""
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
callback_id |
string | Webhook 里原样带回 | 是 |
text |
string | 提示文案 | 否 |
show_alert |
bool | 是否弹窗 | 否 |
url |
string | 打开链接 | 否 |
命令菜单
设置:POST /bot/botapisetcommands
{
"commands": [
{"command": "start", "description": "开始使用"},
{"command": "help", "description": "帮助"},
{"command": "price", "description": "查价"}
]
}
读取:POST /bot/botapigetcommands
群成员禁言
| 路径 | 作用 |
|---|---|
POST /bot/mutemember |
禁言 |
POST /bot/unmutemember |
解除禁言 |
当前不提供「拉取完整群成员列表」类接口,避免与隐私策略冲突;需要定向操作时请用业务侧已知的用户 ID。
示例代码
Python:发文字
import requests
def send_text_message(bot_token, group_id, content):
url = "https://api.bi.ink/bot/sendmessage"
headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}
data = {
"group_id": group_id,
"message_type": "text",
"content": content
}
response = requests.post(url, json=data, headers=headers)
return response.json()
Python:上传后发图
import requests
def upload_file(bot_token, file_path):
url = "https://api.bi.ink/bot/uploadfile"
headers = {"Authorization": f"Bearer {bot_token}"}
with open(file_path, 'rb') as f:
files = {'file': f}
response = requests.post(url, files=files, headers=headers)
result = response.json()
if result.get('code') == 200:
return result['data']['file_id']
raise RuntimeError(result.get('msg', 'upload failed'))
def send_image_message(bot_token, group_id, file_id, caption=""):
url = "https://api.bi.ink/bot/sendmessage"
headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}
data = {
"group_id": group_id,
"message_type": "image",
"file_id": file_id,
"content": caption
}
response = requests.post(url, json=data, headers=headers)
return response.json()
file_id = upload_file(bot_token, "/path/to/image.jpg")
send_image_message(bot_token, "group_123", file_id, "说明")
Python:带按钮
def send_message_with_buttons(bot_token, group_id, content):
url = "https://api.bi.ink/bot/sendmessage"
headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}
data = {
"group_id": group_id,
"message_type": "text",
"content": content,
"extra": {
"inline_keyboard": [
[
{"text": "确认", "callback_data": "confirm"},
{"text": "取消", "callback_data": "cancel"}
]
]
}
}
return requests.post(url, json=data, headers=headers).json()
Python:Flask 收 Webhook
import requests
from flask import Flask, request
app = Flask(__name__)
BOT_TOKEN = "your_bot_token"
API_BASE_URL = "https://api.bi.ink"
@app.route('/webhook', methods=['POST'])
def webhook():
event = request.json
if event.get('event_type') == 'callback_query':
callback_id = event['callback_id']
callback_data = event['callback_data']
message_id = event['message_id']
sender_id = event['sender_id']
if callback_data == 'confirm':
answer_callback(callback_id, '已确认', False)
edit_message(message_id, '已确认', {'inline_keyboard': []})
elif callback_data == 'cancel':
answer_callback(callback_id, '已取消', False)
return 'OK', 200
def answer_callback(callback_id, text, show_alert):
requests.post(
f"{API_BASE_URL}/bot/answercallback",
json={"callback_id": callback_id, "text": text, "show_alert": show_alert},
headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
)
def edit_message(message_id, content, extra):
requests.post(
f"{API_BASE_URL}/bot/editmessage",
json={"message_id": message_id, "content": content, "extra": extra},
headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
)
Go:发文字
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func sendMessage(botToken, groupID, content string) error {
url := "https://api.bi.ink/bot/sendmessage"
data := map[string]interface{}{
"group_id": groupID,
"message_type": "text",
"content": content,
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer "+botToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
Node:Express Webhook
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const BOT_TOKEN = 'your_bot_token';
const API_BASE_URL = 'https://api.bi.ink';
app.post('/webhook', async (req, res) => {
const event = req.body;
if (event.event_type === 'private_message' && event.content === '/start') {
await axios.post(`${API_BASE_URL}/bot/sendmessage`, {
target_user_id: event.sender_id,
message_type: 'text',
content: '欢迎使用'
}, { headers: { Authorization: `Bearer ${BOT_TOKEN}` } });
} else if (event.event_type === 'callback_query') {
await axios.post(`${API_BASE_URL}/bot/answercallback`, {
callback_id: event.callback_id,
text: '收到',
show_alert: false
}, { headers: { Authorization: `Bearer ${BOT_TOKEN}` } });
}
res.status(200).send('OK');
});
app.listen(3000);