开发者文档
简体中文

机器人开发

Bot API 参考

完整列出 Pabal 的 HTTP Bot API 接受的方法、收发的对象以及错误。与 Telegram Bot API 兼容。

Pabal 的 HTTP Bot API 使用与 Telegram Bot API 相同的地址格式、请求、响应和错误。本文档只列出 Pabal 实际接受的内容。这里没有列出的方法会返回 404 Not Found: method not found。如果你是第一次接触,请先阅读创建机器人教程。

发送请求

https://pabal.me/bot<令牌>/<方法>
  • HTTP 方法:GET 和 POST 都可以。
  • 发送参数的四种方式——查询字符串(?chat_id=1&text=hi)、application/x-www-form-urlencoded、application/json,以及上传文件时的 multipart/form-data。也可以混合使用。
  • 对象类型的参数(reply_markup、commands、allowed_updates)在 JSON 正文中直接写成对象或数组,在表单和查询字符串中则写成 JSON 字符串。
  • 方法名不区分大小写(sendMessage = sendmessage)。
  • 正文大小上限为 12MB(超过则返回 413)。
  • 下载文件使用单独的地址 https://pabal.me/file/bot<令牌>/<file_path>(见 getFile)。

响应与错误

响应始终是 JSON。成功时返回 HTTP 200 和 result;失败时返回相应的 HTTP 状态、与之相同的 error_code,以及供人阅读的 description。

{"ok": true, "result": { … }}
{"ok": false, "error_code": 400, "description": "Bad Request: chat not found"}
error_code何时出现description 示例
400参数有误Bad Request: chat not found, Bad Request: message text is empty, Bad Request: message is not modified: …, Bad Request: message to edit not found, Bad Request: wrong file identifier/HTTP URL specified, Bad Request: query is too old and response timeout expired or query ID is invalid
401令牌错误Unauthorized
403没有发送权限Forbidden: bot can't initiate conversation with a user, Forbidden: bot is not a member of the group chat
404方法或文件不存在Not Found: method not found
409设置了 Webhook 却调用 getUpdatesConflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first
413正文超过 12MBRequest Entity Too Large
500服务器内部错误Internal Server Error

Pabal 目前还没有针对全部请求的频率限制,但语音方法有每小时限额,超过时返回 429 Too Many Requests: retry after N(语音通话)。请把程序写成收到 429 时等待 parameters.retry_after 秒后再重试。

接收更新

从以下两种方式中选择一种。两者不能同时使用。

getUpdates

POST/bot<令牌>/getUpdates

获取正在等待的更新(长轮询)。如果设置了 Webhook,则返回 409。

参数类型必填说明
offsetInteger可选只返回编号大于或等于此值的更新。比它小的更新会作为“已收到”被删除。请传入最后处理的 update_id + 1。
limitInteger可选1~100,默认 100
timeoutInteger可选等待的秒数,0~50,默认 0。建议使用 25~30。
allowed_updatesArray of String可选要接收的类型(Update)。留空表示全部默认类型(message、edited_message、callback_query)。语音类型只有写出名称才会送达。传入的列表会作为机器人的设置保留,之后的调用和 Webhook 也会使用(不传则保持原值)

返回值:Array of Update

setWebhook

POST/bot<令牌>/setWebhook

通过 HTTPS 地址接收更新。详细说明请参阅 Webhook 文档。

参数类型必填说明
urlString是https:// 公网地址。传入空字符串会删除 Webhook
secret_tokenString可选1~256 个字符,A-Z a-z 0-9 _ -。通过请求头 X-Telegram-Bot-Api-Secret-Token 发送
allowed_updatesArray of String可选从 message、edited_message、callback_query 中选择。留空表示这三种全部。语音类型(voice_call、voice_call_tool_query、voice_call_transcript)只有写出名称才会送达。不传则保持原值
drop_pending_updatesBoolean可选丢弃正在等待的更新
max_connectionsInteger可选1~100,默认 40。仅保存该值,发送时每个机器人一次只发一个
certificateInputFile不支持返回 400——请使用公共证书
ip_addressString忽略

返回值:True

deleteWebhook

POST/bot<令牌>/deleteWebhook

删除 Webhook,回到 getUpdates。即使没有设置 Webhook 也会成功。

参数类型必填说明
drop_pending_updatesBoolean可选丢弃正在等待的更新

返回值:True

getWebhookInfo

GET/bot<令牌>/getWebhookInfo

Webhook 的状态。没有参数。没有设置 Webhook 时,url 为空字符串。

返回值:WebhookInfo

方法

方法作用
getMe机器人自身的信息
sendMessage发送文字(可带按钮)
sendPhoto发送照片
sendDocument发送文件
sendLocation发送位置(包括实时位置)
sendVenue发送地点(带名称和地址的位置)
sendContact发送联系人名片
editMessageLiveLocation · stopMessageLiveLocation移动或停止实时位置
editMessageText修改已发送消息的文字和按钮
editMessageCaption修改照片说明
editMessageReplyMarkup只修改按钮
deleteMessage删除消息
answerCallbackQuery回答按钮点击
sendChatAction“正在输入”提示(只接收)
getChat对话信息
getFile收到的照片的下载路径
setMyCommands · getMyCommands · deleteMyCommands命令菜单
logOut · close用于兼容(不执行任何操作)
getUpdates · setWebhook · deleteWebhook · getWebhookInfo接收更新(见上文)
setVoiceCallSettings · getVoiceCallSettings · endVoiceCall · sendVoiceCallContext · getVoiceCallUsage · startVoiceCall · answerVoiceCallToolQuery · setVoiceCallApiKey · setVoiceCallMcpServer …语音机器人(见下文语音通话)
chat_id 可以填什么

一对一对话时填用户的 ID(正数),普通群组时填群组 ID(负数),或者填用户的用户名("@hana_lee")。这些都可以从更新的 chat.id 中得知。频道和超级群组的 ID(-100…)目前还不存在(400 chat not found)。

getMe

GET/bot<令牌>/getMe

用于确认令牌是否正确。没有参数。

返回值:User——对于机器人,还会额外带上 can_join_groups(true)、can_read_all_group_messages(true)、supports_inline_queries(false)、can_connect_to_business(false)、has_main_web_app(false)。

sendMessage

POST/bot<令牌>/sendMessage

参数类型必填说明
chat_idInteger 或 String是发送到的对话(参见上面的提示框)
textString是1~4,096 个字符。按原样发送文字
reply_markupInlineKeyboardMarkup · ReplyKeyboardMarkup · ReplyKeyboardRemove · ForceReply可选按钮
disable_notificationBoolean可选静默发送
parse_mode, entities, reply_parameters, link_preview_options …忽略会接收但不使用。不会应用任何格式

返回值:发送出去的 Message

要发送给某个用户,该用户必须先与机器人对话过(403 Forbidden: bot can't initiate conversation with a user)。要发送到群组,机器人必须是该群组的成员。

sendPhoto

POST/bot<令牌>/sendPhoto

参数类型必填说明
chat_idInteger 或 String是发送到的对话
photoInputFile 或 String是用 multipart/form-data 上传的文件(最大 10MB,JPEG、PNG、GIF),或者之前收到的照片的 file_id。暂不支持 URL
captionString可选0~1,024 个字符
reply_markup与 sendMessage 相同可选
disable_notificationBoolean可选

返回值:发送出去的 Message(photo 中带有新的 file_id)

sendDocument

POST/bot<令牌>/sendDocument

参数类型必填说明
chat_idInteger 或 String是发送到的对话
documentInputFile 或 String是用 multipart/form-data 上传的文件(不限格式,最大 20MB),或者之前收到的文件的 file_id。暂不支持 URL
filenameString可选显示给接收方的名称。不填则使用上传文件本身的名称
captionString可选0~1,024 个字符
reply_markup与 sendMessage 相同可选
disable_notificationBoolean可选
thumbnail, disable_content_type_detection忽略会接收但不使用

返回值:发送出去的 Message(document 中带有新的 file_id)

格式(mime_type)根据文件名的扩展名确定。从应用发送的文件最大 2GB,但机器人通过 HTTP 上传和下载的上限与 Telegram 一样,为 20MB。

sendLocation

POST/bot<令牌>/sendLocation

参数类型必填说明
chat_idInteger 或 String是发送到的对话
latitude, longitudeFloat是纬度(−90~90)和经度(−180~180)。超出范围时返回 400 Bad Request: GEO_POINT_INVALID
horizontal_accuracyFloat可选误差半径(米,0~1,500)。四舍五入后以整数保存
live_periodInteger可选填写后即为实时位置:60~86,400 秒,或填 2147483647(0x7FFFFFFF)表示直到停止。其他值返回 400 Bad Request: wrong live_period
headingInteger可选实时位置的行进方向,1~360 度
proximity_alert_radiusInteger可选实时位置的接近提醒半径(米)。会保存并显示,但目前还不会发送提醒
reply_markup与 sendMessage 相同可选
disable_notificationBoolean可选

返回值:发送出去的 Message(location 中带有 Location)

sendVenue

POST/bot<令牌>/sendVenue

参数类型必填说明
chat_idInteger 或 String是发送到的对话
latitude, longitudeFloat是地点的位置(与 sendLocation 相同)
titleString是地点名称
addressString是地址
foursquare_id, foursquare_typeString可选Foursquare 的地点 ID 和类型,按收到的原样传递
google_place_id, google_place_typeString可选Google 的地点 ID 和类型。仅在没有 foursquare_id 时使用
reply_markup与 sendMessage 相同可选
disable_notificationBoolean可选

返回值:发送出去的 Message(venue 中带有 Venue,location 中也有同一位置)

缺少 title 或 address 时返回 400 Bad Request: title and address are required。

sendContact

POST/bot<令牌>/sendContact

参数类型必填说明
chat_idInteger 或 String是发送到的对话
phone_numberString是电话号码,按填写的原样传递
first_nameString是名
last_nameString可选姓
vcardString可选vCard 格式的附加信息,最多 64KB
reply_markup与 sendMessage 相同可选
disable_notificationBoolean可选

返回值:发送出去的 Message(contact 中带有 Contact)

机器人发送的联系人名片不会带 user_id,即使该号码属于某个 Pabal 账号也是如此——机器人没有联系人;如果填上,机器人只要每个号码发一张名片,就能查出号码属于谁。缺少 phone_number 或 first_name 时返回 400 Bad Request: phone_number and first_name are required。

editMessageLiveLocation

POST/bot<令牌>/editMessageLiveLocation

参数类型必填说明
chat_idInteger 或 String是消息所在的对话
message_idInteger是要移动的实时位置(机器人发送的)
latitude, longitudeFloat是新的位置
horizontal_accuracyFloat可选误差半径(米,0~1,500)
headingInteger可选行进方向,1~360 度
proximity_alert_radiusInteger可选接近提醒半径(米)。填 0 则关闭
live_periodInteger可选新的共享时长:从消息发送时刻起算的秒数。最多只能比当前时长多延长一天;填 2147483647 表示直到停止
reply_markupInlineKeyboardMarkup可选新的按钮
inline_message_idString不支持没有内联模式,因此返回 400

返回值:修改后的 Message

已经结束的实时位置——已停止或时长已到——既不能移动,也不能通过延长时长使其恢复(400 Bad Request: message can't be edited)。不是实时位置的消息也一样。

距上一次生效的移动不足 10 秒,或移动距离不足 10 米的移动,服务器不会保存,直接略过。停止以及时长、提醒半径的变更则总会生效。被略过时,返回的 Message 显示最后一次生效的位置,因此每隔几秒发送一次也没有问题。

stopMessageLiveLocation

POST/bot<令牌>/stopMessageLiveLocation

参数为 chat_id、message_id、reply_markup(可选)。让实时位置停在最后的位置。共享时长会缩短为实际经过的时间,因此所有应用都会把它显示为已结束。如果已经停止或结束,返回 400 Bad Request: message is not modified: …。返回值:修改后的 Message。

editMessageText

POST/bot<令牌>/editMessageText

参数类型必填说明
chat_idInteger 或 String是消息所在的对话
message_idInteger是要修改的消息(机器人发送的)
textString是新的文字,1~4,096 个字符
reply_markupInlineKeyboardMarkup可选新的按钮。省略时按钮会被移除(与 Telegram 相同)
inline_message_idString不支持没有内联模式,因此返回 400

返回值:修改后的 Message。修改会立即反映到应用中;用户修改的消息则会以 edited_message 发给机器人。

文字和按钮与之前完全相同时,返回 400 Bad Request: message is not modified: …;试图修改别人的消息时,返回 400 Bad Request: message can't be edited。

editMessageCaption

POST/bot<令牌>/editMessageCaption

参数为 chat_id、message_id、caption(0~1,024 个字符,省略则删除说明)、reply_markup。返回值:修改后的 Message。

editMessageReplyMarkup

POST/bot<令牌>/editMessageReplyMarkup

保持文字不变,只更换按钮。参数为 chat_id、message_id、reply_markup(省略则删除按钮)。返回值:修改后的 Message。

deleteMessage

POST/bot<令牌>/deleteMessage

参数为 chat_id、message_id。在对话双方那里都删除该消息。消息不存在时返回 400 Bad Request: message to delete not found。返回值:True。

answerCallbackQuery

POST/bot<令牌>/answerCallbackQuery

回答用户点击的按钮(CallbackQuery)。必须在 10 秒内回答,且只能回答一次。

参数类型必填说明
callback_query_idString是更新中的 callback_query.id
textString可选在屏幕上方短暂显示的文字
show_alertBoolean可选为 true 时显示为带确认按钮的对话框
urlString可选让应用打开的地址
cache_timeInteger可选应用缓存此回答的秒数

返回值:True。如果为时已晚或已经回答过,返回 400 Bad Request: query is too old and response timeout expired or query ID is invalid。

sendChatAction

POST/bot<令牌>/sendChatAction

为了兼容会接收请求并返回 True,但目前还不会在应用中显示“正在输入…”。

getChat

GET/bot<令牌>/getChat?chat_id=…

参数为 chat_id(数字)。如果是用户,就返回该用户;如果是群组,则仅限机器人是其成员的群组。返回值:Chat。不存在或无权查看时,返回 400 Bad Request: chat not found。

getFile

GET/bot<令牌>/getFile?file_id=…

用收到的照片的 file_id 获取下载路径。返回值:File。然后通过下面的地址下载。

https://pabal.me/file/bot<令牌>/<file_path>

file_id 同时也是取得该照片的凭证。值无效时,返回 400 Bad Request: wrong file identifier/HTTP URL specified。

setMyCommands

POST/bot<令牌>/setMyCommands

参数类型必填说明
commandsArray of BotCommand是最多 100 条
language_codeString可选保存为该语言的列表。目前应用中只显示未指定语言代码的默认列表
scopeBotCommandScope忽略

返回值:True。不符合规则时什么也不保存,返回 400 Bad Request: BOT_COMMAND_INVALID(命令)、BOT_COMMAND_DESCRIPTION_INVALID(说明为空或超过 256 个字符)、BOT_COMMANDS_TOO_MUCH(超过 100 个)。

getMyCommands

GET/bot<令牌>/getMyCommands

参数为 language_code(可选)。返回值:Array of BotCommand。

deleteMyCommands

POST/bot<令牌>/deleteMyCommands

参数为 language_code(可选)。清空该列表。返回值:True。

logOut · close

在 Telegram 中,这两个方法用于迁移到本地 Bot API 服务器。Pabal 没有可以迁移的目标,因此只会接收请求并返回 True。要让令牌失效,请使用 BotFather 的 /revoke。

对象

字段旁边的 可选 表示该字段可能不存在。这里没有列出的 Telegram 其他字段,Pabal 不会发送。

Update

一条新的更新。包含 update_id 以及下面各项中的一个。

字段类型说明
update_idInteger逐次加 1 的编号。用于 getUpdates 的 offset
message 可选Message发给机器人的新消息(一对一对话,或机器人所在群组中的所有消息)
edited_message 可选Message被修改的消息
callback_query 可选CallbackQuery内联按钮点击
voice_call 可选VoiceCall打给语音机器人的通话和机器人打出的电话的开始和结束(需要按名称请求才会送达)
voice_call_tool_query 可选VoiceCallToolQuery通话中模型调用的机器人工具(需要按名称请求才会送达)
voice_call_transcript 可选VoiceCallTranscript通话中文字记录的一段发言(需要按名称请求才会送达)

User

字段类型说明
idInteger用户 ID(只在这台服务器内有意义)
is_botBoolean机器人为 true
first_nameString名字。已删除的账号为 Deleted Account
last_name 可选String姓氏
username 可选String用户名(不带 @)

Chat

字段类型说明
idInteger用户为该用户的 ID(正数),普通群组为负数
typeStringprivate 或 group
title 可选String群组名称(group)
first_name, last_name, username 可选String对方的名字和用户名(private)

Message

字段类型说明
message_idInteger该对话中的消息编号
from 可选User发送者
chatChat消息所在的对话
dateInteger发送时间(Unix 秒)
edit_date 可选Integer最后一次修改的时间
text 可选String文字(不是照片、文件、位置、地点或联系人消息时总会有)
entities 可选Array of MessageEntity文字中的命令、提及、URL、话题标签
photo 可选Array of PhotoSize照片(Pabal 只有一张原图)
document 可选Document文件
location 可选Location位置或实时位置。地点消息的位置也会一并放在这里
venue 可选Venue地点
contact 可选Contact联系人名片
caption 可选String照片说明
caption_entities 可选Array of MessageEntity说明中的命令、提及、URL、话题标签
reply_markup 可选InlineKeyboardMarkup消息上附带的内联按钮

MessageEntity

字段类型说明
typeStringbot_command, mention, url, hashtag
offsetInteger起始位置(UTF-16 代码单元)
lengthInteger长度(UTF-16 代码单元)

由服务器在文字中自动识别并附上。粗体、斜体等格式实体目前还没有。

PhotoSize

字段类型说明
file_idString用于下载(getFile)和再次发送(sendPhoto)的 ID
file_unique_idString同一张照片即使在不同机器人那里也是相同的值。不能用于下载
width, heightInteger像素尺寸
file_sizeInteger字节数

Document

字段类型说明
file_idString用于下载(getFile)和再次发送(sendDocument)的 ID
file_unique_idString同一个文件即使在不同机器人那里也是相同的值。不能用于下载
file_nameString发送方给出的名称
mime_typeString发送方声明的格式
file_sizeInteger字节数

Location

字段类型说明
latitude, longitudeFloat纬度和经度
horizontal_accuracy 可选Float误差半径(米)
live_period 可选Integer实时位置的共享时长:从消息发送时刻起算的秒数。停止后会缩短为实际经过的时间
heading 可选Integer行进方向,1~360 度
proximity_alert_radius 可选Integer接近提醒半径(米)

用户共享的实时位置,每当服务器应用一次移动,都会以 edited_message 再次送达。

Venue

字段类型说明
locationLocation地点的位置
titleString地点名称
addressString地址
foursquare_id, foursquare_type 可选StringFoursquare 的地点 ID 和类型
google_place_id, google_place_type 可选StringGoogle 的地点 ID 和类型

Contact

字段类型说明
phone_numberString发送者填写的原样号码
first_nameString名
last_name 可选String姓
user_id 可选Integer该号码对应的 Pabal 账号。仅当发送者已把此人保存在自己的联系人中,或者就是本人时才会带上
vcard 可选StringvCard 格式的附加信息

File

字段类型说明
file_id, file_unique_idString与 PhotoSize 相同
file_sizeInteger字节数
file_pathStringphotos/<file_id>.jpg 或 documents/<file_id> 形式。接在 /file/bot<令牌>/ 后面即可下载

CallbackQuery

字段类型说明
idString传给 answerCallbackQuery 的 ID
fromUser点击按钮的用户
message 可选Message附带该按钮的消息
chat_instanceString代表该对话的值
data 可选String按钮的 callback_data

InlineKeyboardMarkup

inline_keyboard:Array of Array of InlineKeyboardButton——外层数组是行,内层数组是一行中的按钮。一条消息最多 100 行、100 个按钮。

InlineKeyboardButton

字段类型说明
textString按钮上的文字
callback_data 二选一String点击后发给机器人的值,1~64 字节
url 二选一String点击后打开的地址

switch_inline_query、web_app、login_url、pay 等其他类型目前还没有(400)。

ReplyKeyboardMarkup

字段类型说明
keyboardArray of Array of KeyboardButton输入框下方的按钮面板
resize_keyboard, one_time_keyboard, is_persistent, selective 可选Boolean自动调整大小 · 使用一次后隐藏 · 始终显示 · 只对特定用户显示
input_field_placeholder 可选String输入框中的提示文字

KeyboardButton

一个字符串,或者一个包含 text 以及可选字段 request_contact(发送我的联系方式)、request_location(发送我的位置,Boolean)的对象。

ReplyKeyboardRemove

{"remove_keyboard": true}——隐藏按钮面板。selective 可选。

ForceReply

{"force_reply": true}——应用会以回复这条消息的状态打开输入框。selective、input_field_placeholder 可选。

BotCommand

字段类型说明
commandString1~32 个小写英文字母、数字和下划线(不带 /)
descriptionString1~256 个字符

WebhookInfo

字段类型说明
urlStringWebhook 地址,没有则为空字符串
has_custom_certificateBoolean始终为 false
pending_update_countInteger等待送达的更新数量
ip_address 可选String最近一次发送的目标 IP
last_error_date 可选Integer最后一次失败的时间(Unix 秒)
last_error_message 可选String最后一次失败的原因(列表)
max_connections 可选Integer在 setWebhook 中传入的值
allowed_updates 可选Array of String在 setWebhook 中传入的值

语音通话

这些方法只有 Pabal 才有。语音机器人是指有人在应用中给它打电话时由 AI 语音模型接听的机器人,这些方法用来设定该模型的设置并处理通话。需要开启哪些条件、如何开启以及示例,请参阅语音机器人指南。即使服务器上关闭了语音,这些方法也依然存在,可以读取设置;但语音已关闭或尚未获得运营方允许的机器人,除了关闭和删除之外不能修改设置(403 VOICE_NOT_AVAILABLE)。

setVoiceCallSettings

POST/bot<令牌>/setVoiceCallSettings

修改机器人的语音设置。只修改所发送的字段;先检查全部内容,然后一次写入,或者全部拒绝。每个机器人每小时 30 次(与 @BotFather 合计)。

参数类型必填说明
enabledBoolean可选只有在 @BotFather 中同意语音机器人规则后才能开启(403 VOICE_RULES_NOT_ACCEPTED)。关闭随时可以
instructionsString可选模型的指令,最多 8,192 字节。"" 表示删除(已开启的托管机器人不行)
greetingString可选第一句问候,最多 512 字节。为 "" 时由模型自行决定
voiceString可选音色 id,默认 kore(列表)
languageString可选ko-KR(默认)、en-US、ja-JP、cmn-CN、fr-FR、es-US、id-ID、vi-VN、ar-EG(列表)。不区分大小写,zh-CN 会保存为 cmn-CN。韩语、英语以外的机器人要等运营方阅读指令和问候语并允许后才会接听电话
max_call_durationInteger可选秒,60 ~ limits.max_call_duration
max_concurrent_callsInteger可选1 ~ limits.max_concurrent_calls
toolsArray of VoiceCallTool可选通话中模型调用的机器人工具:{"name", "description", "parameters"?, "timeout_ms"?}。规则见定义工具。表单中为 JSON 字符串
transcriptBoolean可选文字记录开关。只有同意机器人所有者条款后才能开启
modeString可选managed(Pabal 的 AI 模型)或 stream(音频流模式)
stream_url, stream_secretString可选与 mode=stream 一起使用。机密值只能放在请求体中

返回值:True

getVoiceCallSettings

GET/bot<令牌>/getVoiceCallSettings

没有参数。返回当前设置、机器人现在能否接听电话(available、unavailable_reason)、服务器的限额、音色和语言列表、工具查询和文字记录的去向,以及自有密钥、音频流模式和 MCP 服务器的状态。不显示密钥和机密值,只显示指纹。字段见语音机器人——查看当前设置。

返回值:VoiceCallSettings(对象)

endVoiceCall

POST/bot<令牌>/endVoiceCall

参数类型必填说明
voice_call_idString是voice_call.id
farewellBoolean可选默认 true:模型简短道别后挂断(10 秒内没挂断则由服务器结束)。为 false 时立即挂断

返回值:True。如果不是这个机器人正在进行的通话,返回 400 VOICE_CALL_NOT_FOUND。

sendVoiceCallContext

POST/bot<令牌>/sendVoiceCallContext

参数类型必填说明
voice_call_idString是已接通的通话
textString是机器人所有者给模型的备注。最多 2,000 个字符、6,144 字节,按内容规则检查
respondBoolean可选默认 false。为 true 时模型立即回应

返回值:True。接通前返回 VOICE_CALL_NOT_ACTIVE,音频流通话返回 VOICE_CONTEXT_NOT_SUPPORTED,过长返回 VOICE_CONTEXT_TOO_LONG,每通电话每分钟超过 10 条返回 429。

getVoiceCallUsage

GET/bot<令牌>/getVoiceCallUsage

参数类型必填说明
periodString可选today(默认)或 month
monthString可选YYYY-MM,只能与 period=month 一起使用

返回值:period、from_date、to_date、calls、seconds、missed、refused(busy·budget·unavailable)、platform_seconds、own_key_seconds、remaining_seconds_today(bot·owner),曾开启过外呼的机器人还有 outbound(today·limits)——日期分界以服务器的时区为准

startVoiceCall

POST/bot<令牌>/startVoiceCall

机器人给人打电话。只有机器人所有者在 @BotFather 中开启、并经运营方审核的机器人,才能打给许可了该机器人的人。回答和判定见语音机器人——拨打。

参数类型必填说明
user_idInteger是要拨打的人
purposeString是reminder、wake_up、delivery、appointment 中机器人选择的一个
contextString是只给模型的说明,最多 1,000 个字符、3,072 字节,按内容规则检查
max_durationInteger可选接听后的最长秒数,30–300(不超过机器人的上限)。默认 180
ring_timeoutInteger可选响铃秒数,30–45。默认 40

返回值:{"voice_call_id": "…"}——只表示已受理,是否响铃、是否接听以 voice_call 更新告知。拒绝:403 VOICE_OUTBOUND_OFF: <原因>、403 USER_UNAVAILABLE(响应体始终相同)、429、503 VOICE_UNAVAILABLE。不能通过 Webhook 响应调用。

answerVoiceCallToolQuery

POST/bot<令牌>/answerVoiceCallToolQuery

参数类型必填说明
tool_query_idString是VoiceCallToolQuery 的 id
resultString · Object · Array二选一工具的结果,最多 16,384 字节
errorString二选一机器人的失败说明,最多 512 字节

返回值:True。第一次回答就是最终回答。太晚时返回 400 TOOL_QUERY_EXPIRED: answered|timeout|cancelled|call_ended|unreachable,未知的 id 返回 TOOL_QUERY_ID_INVALID,回答被拒绝时返回 TOOL_RESULT_EMPTY·TOOL_RESULT_INVALID·TOOL_RESULT_TOO_LONG·TOOL_ERROR_TOO_LONG·TOOL_RESULT_REFUSED: <代码>。对 Webhook 的工具查询 POST,也可以用响应体回答。

setVoiceCallApiKey · deleteVoiceCallApiKey

POST/bot<令牌>/setVoiceCallApiKey

参数类型必填说明
providerString是google(Vertex AI 服务账号 JSON 密钥)或 openai(sk-…)
api_keyString是密钥。只能放在请求体中(放在查询中返回 400),最多 8KiB

返回值:True——只有通过网关的测试会话后才会保存。API_KEY_INVALID、API_KEY_NO_REALTIME_ACCESS、503 API_KEY_CHECK_UNAVAILABLE(不保存)、403 VOICE_OWN_KEY_NOT_AVAILABLE(这台服务器不接受自有密钥)。deleteVoiceCallApiKey 没有参数,始终返回 True。这两个方法都不能用 bots.sendCustomRequest 调用,setVoiceCallApiKey 也不能在 Webhook 响应中调用。详见自有模型密钥。

MCP 服务器方法

方法参数返回值
setVoiceCallMcpServerlabel、url、auth(对象),可选 audience、allowed_tools、requested_level、timeout_ms、tools(覆盖分类)、declaration、auto_repin注册结果(status、job_id)。接收方发生变化时返回 400 MCP_CHANGE_NEEDS_CONFIRMATION,之后需在 @BotFather 中确认
refreshVoiceCallMcpServerlabel重新检查(refreshing: true、job_id)
deleteVoiceCallMcpServerlabelTrue——即使 MCP 已关闭也可以
getVoiceCallMcpBinding无iss、sub(bot:<id>)、issuer_document、jwks_uri、audiences
createVoiceCallMcpClientKeylabel公开的 jwk、thumbprint(私钥不会离开 Pabal)

auth 和机密值只能放在请求体中发送。在关闭了 MCP 的服务器上返回 403 VOICE_NOT_AVAILABLE: MCP tools are not available on this server。详见语音机器人——MCP 服务器。

如何接收语音更新

voice_call、voice_call_tool_query、voice_call_transcript 只有按名称请求才会送达——请把它们写进 getUpdates 或 setWebhook 的 allowed_updates。传空列表收不到,请求之前发生的也不会保留。有 Webhook 时,工具查询以单独的 POST 送达;最近 15 秒内调用过 getUpdates 时,则放在下一次 getUpdates 的最前面。

VoiceCall

字段类型说明
idString通话 id(无符号十进制数)
directionStringincoming(打给机器人的电话)或 outgoing(机器人打出的电话)。总是存在
eventStringstarted、ended、missed、refused;机器人打出的电话为 started、ended、not_answered、failed
from 可选User仅限打给机器人的电话——来电者:id、is_bot、first_name、last_name、language_code。没有用户名和手机号码
to 可选Object仅限机器人打出的电话——{"id": …},只有接听者的 ID
purpose 可选String仅限机器人打出的电话——请求的目的
dateInteger发生的时间(Unix 秒)。started 对应用的通话是密钥交换完成时,对 Apple Watch 的通话是手表的声音接通时。在等待文字记录或开启了保存对话的服务器上,ended 最多会晚 10 秒送达。机器人打出的电话则无论服务器如何设置,接听后的 ended 都要等待网关的用量,最多晚 10 秒送达
max_duration 可选Integer这通电话的最长时间(秒)——started、ended
start_date, duration 可选Integer接通时间和通话秒数(服务器时钟)——ended
end_reason 可选Stringcaller(机器人打出的电话为 callee)、bot、max_length、failed、operator、suspended——ended、missed
refused_reason 可选Stringbusy、budget、unavailable——refused
transcript 可选Object{"turns": [{"role", "text", "offset_ms"}], "truncated"}——ended,开启了文字记录时。机器人打出的电话没有

VoiceCall 中没有告诉你来电者是否选择了保存对话的字段。这是有意为之——那些文字属于来电者本人,不会发给机器人。因此,在开启了保存对话的服务器上,所有非音频流模式通话的 ended 都会等待同样的时间,而且在所有通话中,通话记录之后那条消息的编号都比记录大 31 以上(编号会预先占用)。

VoiceCallToolQuery

字段类型说明
idString传给 answerVoiceCallToolQuery 的 id
voice_call_idString通话 id
fromUser来电者(字段与 VoiceCall 相同)
nameString工具名
argumentsString参数,JSON 对象的文本(服务器已检查)
budget_msInteger从收到时起,到回答必须送达服务器为止的毫秒数

VoiceCallTranscript

字段类型说明
voice_call_idString通话 id
seqInteger发言编号
roleStringcaller 或 bot
textStringAI 写下的文字。含有银行卡号或居民登记号时,数字会变成 *
is_finalBoolean始终为 true
offset_ms, dateInteger从通话声音开始时算起的毫秒数,以及时间

只通过 HTTP Bot API 送达。整通电话的内容在已结束的 voice_call 的 transcript 中。

音频流模式(mode=stream)

在音频流模式下,通话声音不是发给 Pabal 的 AI 模型,而是发给机器人所有者的服务器。向 setVoiceCallSettings 发送 mode=stream、stream_url=wss://…、stream_secret=…(32~128 个可打印 ASCII 字符,只能放在请求体中)后,Pabal 的网关会试着连接一次该地址(探测),成功后开启。需要机器人所有者条款,以及包含音频流确认窗口的应用版本。设置、探测结果和示例见语音机器人——音频流模式。

  • 连接:TLS 1.2 及以上,与 URL 中名称相符的公共证书,子协议 pabal.voice.v1,不压缩,每条消息最多 64KiB、文本最多 4KiB,不重定向。
  • 签名:X-Pabal-Voice-Signature: t=…,nonce=…,call=…,v1=HMAC-SHA256(stream_secret, "pabal-voice-stream/1\n<t>\n<nonce>\n<call>\n<host>\n<path?query>")。host 是你提供的 URL 的主机。需检查 300 秒、nonce 只用一次、逐字节比较,以及 start.call_id 是否与 call 相同(详见)。
  • 声音:文本消息是 JSON 事件,二进制是 PCM16 小端序、单声道、24 kHz。来电者的声音为 20 ms(960 字节)的分片。
  • Pabal → 机器人:start(一次) · live(AI 提示已结束) · 声音 · mark · cleared · buffer_full · stop(→ 以 1000 关闭)。
  • 机器人 → Pabal:ready(start 之后 3 秒内,最先发送) · 声音(live 之后) · clear · mark · hangup。

每条消息的具体格式见语音机器人——规范中的表格。

语音方法的错误

语音方法的错误代码及含义汇总在语音机器人——错误中。403 的形式为 Forbidden: <代码>: <说明>(VOICE_RULES_NOT_ACCEPTED、VOICE_NOT_AVAILABLE、VOICE_SUSPENDED、VOICE_OWNER_TERMS_NOT_ACCEPTED、VOICE_OWN_KEY_NOT_AVAILABLE、VOICE_STREAM_NOT_AVAILABLE、VOICE_OUTBOUND_OFF),只有 USER_UNAVAILABLE 不带说明,始终是 Forbidden: USER_UNAVAILABLE;超过每小时限额时返回 429 和 retry_after。

与 Telegram Bot API 的不同之处

  • 更新类型:只有 message、edited_message、callback_query,以及 Pabal 独有的语音机器人类型(voice_call、voice_call_tool_query、voice_call_transcript)。没有频道帖子、内联查询、支付、投票、成员变更(my_chat_member)等。
  • 格式:忽略 parse_mode 和 entities,按原样发送文字。只有命令、提及、URL、话题标签会自动显示。
  • 对话类型:只有一对一对话和普通群组。没有频道、超级群组和论坛话题。
  • 媒体:只有照片、文件(sendDocument)以及位置、实时位置、地点和联系人。没有能作为视频或语音播放的消息,也没有贴纸、相册(sendMediaGroup)和投票,不能通过 URL 发送。通过 HTTP 上传和下载的上限为 20MB。
  • 位置:实时位置的接近提醒(proximity_alert_radius)只保存,从不发送。10 秒、10 米以内的移动会被略过而不生效;机器人发送的联系人名片不带 user_id。
  • 群组中的机器人:没有隐私模式,会收到群组中的所有消息。
  • 队列:尚未取走的更新,每个机器人最多在内存中保留最近 1,000 条,服务器重启时会丢失(Telegram 保留 24 小时)。
  • Webhook:一次发送一个、按顺序发送(max_connections 只做保存),不接受自签名证书,没有端口限制。
  • ID:用户、消息、文件的 ID 只在这台服务器内有意义。由于没有频道和超级群组,也没有 -100… 形式的 ID。
  • 不存在的方法:上面列表中没有的方法(forwardMessage、copyMessage、sendVideo、sendPoll、getChatMember、banChatMember、answerInlineQuery …)会返回 404 Not Found: method not found。