Tài liệu nhà phát triển
Tiếng Việt

Phát triển bot

Tham chiếu Bot API

Toàn bộ phương thức mà HTTP Bot API của Pabal hỗ trợ, cùng các đối tượng trao đổi và lỗi. Tương thích với Telegram Bot API.

HTTP Bot API của Pabal dùng cùng định dạng địa chỉ, yêu cầu, phản hồi và lỗi như Telegram Bot API. Tài liệu này chỉ ghi lại những gì Pabal thực sự hỗ trợ. Các phương thức không có ở đây sẽ trả về 404 Not Found: method not found. Nếu bạn mới bắt đầu, hãy xem hướng dẫn tạo bot trước.

Gửi yêu cầu

https://pabal.me/bot<token>/<phương-thức>
  • Phương thức HTTP: dùng được cả GET và POST.
  • Bốn cách gửi tham số — chuỗi truy vấn (?chat_id=1&text=hi), application/x-www-form-urlencoded, application/json, và multipart/form-data khi tải tệp lên. Có thể kết hợp các cách với nhau.
  • Tham số dạng đối tượng (reply_markup, commands, allowed_updates) được truyền nguyên dạng đối tượng/mảng trong phần thân JSON, còn trong form hay chuỗi truy vấn thì truyền dưới dạng chuỗi JSON.
  • Tên phương thức không phân biệt chữ hoa chữ thường (sendMessage = sendmessage).
  • Kích thước phần thân tối đa 12MB (vượt quá thì trả về 413).
  • Tải tệp xuống dùng địa chỉ riêng https://pabal.me/file/bot<token>/<file_path> (getFile).

Phản hồi và lỗi

Phản hồi luôn là JSON. Nếu thành công thì là HTTP 200 kèm result; nếu thất bại thì là mã trạng thái HTTP tương ứng, kèm error_code trùng với mã đó và description để con người đọc.

{"ok": true, "result": { … }}
{"ok": false, "error_code": 400, "description": "Bad Request: chat not found"}
error_codeKhi nàoVí dụ description
400Tham số saiBad 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
401Token saiUnauthorized
403Không có quyền gửiForbidden: bot can't initiate conversation with a user, Forbidden: bot is not a member of the group chat
404Phương thức hoặc tệp không tồn tạiNot Found: method not found
409Gọi getUpdates khi đang có webhookConflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first
413Phần thân vượt quá 12MBRequest Entity Too Large
500Lỗi nội bộ máy chủInternal Server Error

Pabal hiện chưa giới hạn tốc độ cho toàn bộ yêu cầu, nhưng các phương thức thoại có giới hạn theo giờ nên có thể trả về 429 Too Many Requests: retry after N (Cuộc gọi thoại). Hãy viết mã sao cho khi nhận 429 thì đợi parameters.retry_after giây rồi gửi lại.

Nhận update

Dùng một trong hai cách. Không thể dùng cả hai cùng lúc.

getUpdates

POST/bot<token>/getUpdates

Lấy các update đang chờ (long polling). Nếu đang thiết lập webhook thì trả về 409.

Tham sốKiểuBắt buộcMô tả
offsetIntegerTùy chọnChỉ lấy các update có số từ giá trị này trở lên. Những update nhỏ hơn được coi là "đã nhận" và bị xóa. Hãy truyền update_id + 1 của update cuối cùng đã xử lý.
limitIntegerTùy chọn1–100, mặc định 100
timeoutIntegerTùy chọnSố giây chờ, 0–50, mặc định 0. Nên dùng 25–30.
allowed_updatesArray of StringTùy chọnCác loại cần nhận (Update). Để trống là nhận mọi loại mặc định (message, edited_message, callback_query). Các loại thoại chỉ được gửi khi ghi rõ tên. Danh sách đã truyền được lưu thành cài đặt của bot và được dùng cả cho lần gọi sau lẫn cho webhook (nếu không truyền thì giữ nguyên giá trị trước đó)

Trả về: Array of Update

setWebhook

POST/bot<token>/setWebhook

Nhận update tại một địa chỉ HTTPS. Giải thích chi tiết có trong tài liệu Webhook.

Tham sốKiểuBắt buộcMô tả
urlStringCóĐịa chỉ công khai https://. Chuỗi rỗng sẽ xóa webhook
secret_tokenStringTùy chọn1–256 ký tự, A-Z a-z 0-9 _ -. Được gửi trong header X-Telegram-Bot-Api-Secret-Token của yêu cầu
allowed_updatesArray of StringTùy chọnChọn trong message, edited_message, callback_query. Để trống là nhận cả ba loại này. Các loại thoại (voice_call, voice_call_tool_query, voice_call_transcript) chỉ được gửi khi ghi rõ tên. Nếu không truyền thì giữ nguyên giá trị trước đó
drop_pending_updatesBooleanTùy chọnBỏ các update đang chờ
max_connectionsIntegerTùy chọn1–100, mặc định 40. Chỉ được lưu lại; mỗi bot được gửi từng update một
certificateInputFileKhông hỗ trợ400 — hãy dùng chứng chỉ công khai
ip_addressStringBỏ qua

Trả về: True

deleteWebhook

POST/bot<token>/deleteWebhook

Xóa webhook và quay lại dùng getUpdates. Vẫn thành công kể cả khi không có webhook.

Tham sốKiểuBắt buộcMô tả
drop_pending_updatesBooleanTùy chọnBỏ các update đang chờ

Trả về: True

getWebhookInfo

GET/bot<token>/getWebhookInfo

Trạng thái webhook. Không có tham số. Nếu không có webhook thì url là chuỗi rỗng.

Trả về: WebhookInfo

Phương thức

Phương thứcTác dụng
getMeThông tin của chính bot
sendMessageGửi văn bản (kể cả nút bấm)
sendPhotoGửi ảnh
sendDocumentGửi tệp
sendLocationGửi vị trí (kể cả vị trí trực tiếp)
sendVenueGửi địa điểm (vị trí có tên và địa chỉ)
sendContactGửi thẻ liên hệ
editMessageLiveLocation · stopMessageLiveLocationDi chuyển hoặc dừng vị trí trực tiếp
editMessageTextSửa nội dung và nút của tin nhắn đã gửi
editMessageCaptionSửa chú thích ảnh
editMessageReplyMarkupChỉ sửa nút
deleteMessageXóa tin nhắn
answerCallbackQueryTrả lời lượt bấm nút
sendChatActionHiển thị "đang nhập" (chỉ nhận yêu cầu)
getChatThông tin cuộc trò chuyện
getFileĐường dẫn tải xuống của ảnh đã nhận
setMyCommands · getMyCommands · deleteMyCommandsMenu lệnh
logOut · closeĐể tương thích (không làm gì cả)
getUpdates · setWebhook · deleteWebhook · getWebhookInfoNhận update (ở trên)
setVoiceCallSettings · getVoiceCallSettings · endVoiceCall · sendVoiceCallContext · getVoiceCallUsage · startVoiceCall · answerVoiceCallToolQuery · setVoiceCallApiKey · setVoiceCallMcpServer …Bot thoại (xem Cuộc gọi thoại bên dưới)
Giá trị có thể dùng cho chat_id

Với trò chuyện 1:1 là ID của người dùng (số dương), với nhóm cơ bản là ID nhóm (số âm), hoặc tên người dùng của người đó ("@hana_lee"). Tất cả đều có thể biết qua chat.id của update. ID của kênh và siêu nhóm (-100…) hiện chưa có (400 chat not found).

getMe

GET/bot<token>/getMe

Dùng để kiểm tra token có đúng không. Không có tham số.

Trả về: User — với bot có thêm 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<token>/sendMessage

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện cần gửi đến (xem khung ở trên)
textStringCó1–4.096 ký tự. Được gửi nguyên văn
reply_markupInlineKeyboardMarkup · ReplyKeyboardMarkup · ReplyKeyboardRemove · ForceReplyTùy chọnNút bấm
disable_notificationBooleanTùy chọnGửi không kèm âm thanh
parse_mode, entities, reply_parameters, link_preview_options …Bỏ quaĐược nhận nhưng không dùng. Định dạng không được áp dụng

Trả về: Message đã gửi

Muốn gửi cho một người thì người đó phải nhắn cho bot trước (403 Forbidden: bot can't initiate conversation with a user). Muốn gửi vào nhóm thì bot phải là thành viên của nhóm đó.

sendPhoto

POST/bot<token>/sendPhoto

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện cần gửi đến
photoInputFile hoặc StringCóTệp tải lên bằng multipart/form-data (tối đa 10MB, JPEG, PNG, GIF), hoặc file_id của ảnh đã nhận trước đó. Chưa hỗ trợ URL
captionStringTùy chọn0–1.024 ký tự
reply_markupGiống sendMessageTùy chọn
disable_notificationBooleanTùy chọn

Trả về: Message đã gửi (có file_id mới trong photo)

sendDocument

POST/bot<token>/sendDocument

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện cần gửi đến
documentInputFile hoặc StringCóTệp tải lên bằng multipart/form-data (không giới hạn định dạng, tối đa 20MB), hoặc file_id của tệp đã nhận trước đó. Chưa hỗ trợ URL
filenameStringTùy chọnTên hiển thị cho bên nhận. Bỏ trống thì dùng tên của tệp đã tải lên
captionStringTùy chọn0–1.024 ký tự
reply_markupGiống sendMessageTùy chọn
disable_notificationBooleanTùy chọn
thumbnail, disable_content_type_detectionBỏ quaĐược nhận nhưng không dùng

Trả về: Message đã gửi (có file_id mới trong document)

Định dạng (mime_type) được xác định từ phần mở rộng của tên tệp. Tệp do ứng dụng gửi lên tới 2GB, nhưng tệp mà bot tải lên và tải xuống qua HTTP thì tối đa 20MB, giống Telegram.

sendLocation

POST/bot<token>/sendLocation

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện cần gửi đến
latitude, longitudeFloatCóVĩ độ (−90–90) và kinh độ (−180–180). Nằm ngoài phạm vi thì trả về 400 Bad Request: GEO_POINT_INVALID
horizontal_accuracyFloatTùy chọnBán kính sai số tính bằng mét, 0–1.500. Được làm tròn thành số nguyên khi lưu
live_periodIntegerTùy chọnNếu truyền thì tin nhắn trở thành vị trí trực tiếp: 60–86.400 giây, hoặc 2147483647 (0x7FFFFFFF) cho đến khi dừng. Giá trị khác trả về 400 Bad Request: wrong live_period
headingIntegerTùy chọnHướng di chuyển của vị trí trực tiếp, 1–360 độ
proximity_alert_radiusIntegerTùy chọnBán kính cảnh báo đến gần của vị trí trực tiếp, tính bằng mét. Được lưu và hiển thị nhưng hiện chưa gửi cảnh báo
reply_markupGiống sendMessageTùy chọn
disable_notificationBooleanTùy chọn

Trả về: Message đã gửi (có Location trong location)

sendVenue

POST/bot<token>/sendVenue

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện cần gửi đến
latitude, longitudeFloatCóVị trí của địa điểm (giống sendLocation)
titleStringCóTên địa điểm
addressStringCóĐịa chỉ
foursquare_id, foursquare_typeStringTùy chọnID và loại địa điểm của Foursquare, được chuyển đi nguyên như đã nhận
google_place_id, google_place_typeStringTùy chọnID và loại địa điểm của Google. Chỉ dùng khi không có foursquare_id
reply_markupGiống sendMessageTùy chọn
disable_notificationBooleanTùy chọn

Trả về: Message đã gửi (có Venue trong venue, và cùng vị trí đó trong location)

Thiếu title hoặc address thì trả về 400 Bad Request: title and address are required.

sendContact

POST/bot<token>/sendContact

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện cần gửi đến
phone_numberStringCóSố điện thoại, được chuyển đi nguyên như đã viết
first_nameStringCóTên
last_nameStringTùy chọnHọ
vcardStringTùy chọnThông tin bổ sung ở định dạng vCard, tối đa 64KB
reply_markupGiống sendMessageTùy chọn
disable_notificationBooleanTùy chọn

Trả về: Message đã gửi (có Contact trong contact)

Thẻ liên hệ do bot gửi không bao giờ kèm user_id, kể cả khi số đó thuộc về một tài khoản Pabal — bot không có danh bạ, và nếu điền vào thì bot có thể gửi mỗi số một thẻ để dò ra số đó là của ai. Thiếu phone_number hoặc first_name thì trả về 400 Bad Request: phone_number and first_name are required.

editMessageLiveLocation

POST/bot<token>/editMessageLiveLocation

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện chứa tin nhắn
message_idIntegerCóVị trí trực tiếp cần di chuyển (do bot gửi)
latitude, longitudeFloatCóVị trí mới
horizontal_accuracyFloatTùy chọnBán kính sai số tính bằng mét, 0–1.500
headingIntegerTùy chọnHướng di chuyển, 1–360 độ
proximity_alert_radiusIntegerTùy chọnBán kính cảnh báo đến gần tính bằng mét. 0 là tắt
live_periodIntegerTùy chọnThời gian chia sẻ mới, tính bằng giây kể từ lúc gửi tin nhắn. Không thể kéo dài quá một ngày so với thời gian hiện tại; 2147483647 nghĩa là cho đến khi dừng
reply_markupInlineKeyboardMarkupTùy chọnNút mới
inline_message_idStringKhông hỗ trợChưa có chế độ inline nên trả về 400

Trả về: Message đã sửa

Vị trí trực tiếp đã kết thúc — đã dừng, hoặc đã hết thời gian — thì không thể di chuyển, cũng không thể khôi phục bằng cách kéo dài thời gian (400 Bad Request: message can't be edited). Tin nhắn không phải vị trí trực tiếp cũng vậy.

Lần di chuyển diễn ra chưa đầy 10 giây sau lần được áp dụng gần nhất, hoặc chưa đến 10 m, sẽ được bỏ qua mà không lưu. Việc dừng và việc đổi thời gian hay bán kính cảnh báo luôn được áp dụng. Khi một lần di chuyển bị bỏ qua, Message trả về cho thấy vị trí được áp dụng gần nhất, nên gửi vài giây một lần cũng không sao.

stopMessageLiveLocation

POST/bot<token>/stopMessageLiveLocation

Tham số gồm chat_id, message_id, reply_markup (tùy chọn). Dừng vị trí trực tiếp tại chỗ cuối cùng. Thời gian chia sẻ được rút ngắn lại còn đúng khoảng thời gian thực sự đã trôi qua, nên mọi ứng dụng đều hiển thị nó là đã kết thúc. Nếu đã dừng hoặc đã kết thúc thì trả về 400 Bad Request: message is not modified: …. Trả về: Message đã sửa.

editMessageText

POST/bot<token>/editMessageText

Tham sốKiểuBắt buộcMô tả
chat_idInteger hoặc StringCóCuộc trò chuyện chứa tin nhắn
message_idIntegerCóTin nhắn cần sửa (do bot gửi)
textStringCóNội dung mới, 1–4.096 ký tự
reply_markupInlineKeyboardMarkupTùy chọnNút mới. Nếu bỏ đi thì nút sẽ biến mất (giống Telegram)
inline_message_idStringKhông hỗ trợChưa có chế độ inline nên trả về 400

Trả về: Message đã sửa. Thay đổi hiện ngay trong ứng dụng; tin nhắn do người dùng sửa sẽ đến bot dưới dạng edited_message.

Nếu nội dung và nút giống hệt trước thì trả về 400 Bad Request: message is not modified: …; nếu cố sửa tin nhắn của người khác thì là 400 Bad Request: message can't be edited.

editMessageCaption

POST/bot<token>/editMessageCaption

Tham số gồm chat_id, message_id, caption (0–1.024 ký tự, bỏ đi thì chú thích bị xóa), reply_markup. Trả về: Message đã sửa.

editMessageReplyMarkup

POST/bot<token>/editMessageReplyMarkup

Giữ nguyên nội dung, chỉ đổi nút. Tham số gồm chat_id, message_id, reply_markup (bỏ đi thì nút bị xóa). Trả về: Message đã sửa.

deleteMessage

POST/bot<token>/deleteMessage

Tham số gồm chat_id, message_id. Xóa tin nhắn ở cả hai phía của cuộc trò chuyện. Nếu tin nhắn không tồn tại thì trả về 400 Bad Request: message to delete not found. Trả về: True.

answerCallbackQuery

POST/bot<token>/answerCallbackQuery

Trả lời nút mà người dùng đã bấm (CallbackQuery). Chỉ có thể trả lời trong vòng 10 giây và một lần duy nhất.

Tham sốKiểuBắt buộcMô tả
callback_query_idStringCócallback_query.id của update
textStringTùy chọnDòng chữ hiện thoáng qua ở đầu màn hình
show_alertBooleanTùy chọnNếu true thì hiện hộp thoại có nút xác nhận
urlStringTùy chọnĐịa chỉ để ứng dụng mở
cache_timeIntegerTùy chọnSố giây ứng dụng ghi nhớ câu trả lời này

Trả về: True. Nếu quá muộn hoặc đã trả lời rồi thì là 400 Bad Request: query is too old and response timeout expired or query ID is invalid.

sendChatAction

POST/bot<token>/sendChatAction

Được nhận để tương thích và trả về True, nhưng hiện chưa hiển thị "đang nhập…" trong ứng dụng.

getChat

GET/bot<token>/getChat?chat_id=…

Tham số là chat_id (số). Nếu là người thì trả về người đó; nếu là nhóm thì chỉ những nhóm mà bot là thành viên. Trả về: Chat. Nếu không tồn tại hoặc không được xem thì trả về 400 Bad Request: chat not found.

getFile

GET/bot<token>/getFile?file_id=…

Dùng file_id của ảnh đã nhận để lấy đường dẫn tải xuống. Trả về: File. Sau đó tải xuống từ địa chỉ này.

https://pabal.me/file/bot<token>/<file_path>

file_id cũng chính là quyền lấy ảnh đó. Nếu giá trị không hợp lệ thì trả về 400 Bad Request: wrong file identifier/HTTP URL specified.

setMyCommands

POST/bot<token>/setMyCommands

Tham sốKiểuBắt buộcMô tả
commandsArray of BotCommandCóTối đa 100 lệnh
language_codeStringTùy chọnLưu thành danh sách riêng cho ngôn ngữ đó. Hiện ứng dụng chỉ hiển thị danh sách mặc định (không có mã ngôn ngữ)
scopeBotCommandScopeBỏ qua

Trả về: True. Nếu menu không đúng quy tắc thì không lưu gì cả: 400 Bad Request: BOT_COMMAND_INVALID (lệnh), BOT_COMMAND_DESCRIPTION_INVALID (mô tả trống hoặc dài quá 256 ký tự), BOT_COMMANDS_TOO_MUCH (quá 100 lệnh).

getMyCommands

GET/bot<token>/getMyCommands

Tham số là language_code (tùy chọn). Trả về: Array of BotCommand.

deleteMyCommands

POST/bot<token>/deleteMyCommands

Tham số là language_code (tùy chọn). Làm trống danh sách đó. Trả về: True.

logOut · close

Trên Telegram, đây là các phương thức dùng khi chuyển sang máy chủ Bot API cục bộ. Pabal không có nơi nào để chuyển sang, nên chỉ nhận yêu cầu và trả về True. Muốn vô hiệu hóa token, hãy dùng /revoke của BotFather.

Đối tượng

tùy chọn bên cạnh một trường nghĩa là trường đó có thể không có. Những trường khác của Telegram không được liệt kê ở đây thì Pabal không gửi.

Update

Một tin mới. Chứa update_id và một trong các trường dưới đây.

TrườngKiểuMô tả
update_idIntegerSố tăng thêm 1 sau mỗi update. Dùng cho offset của getUpdates
message tùy chọnMessageTin nhắn mới gửi đến bot (1:1, hoặc mọi tin nhắn trong nhóm mà bot là thành viên)
edited_message tùy chọnMessageTin nhắn đã được sửa
callback_query tùy chọnCallbackQueryLượt bấm nút inline
voice_call tùy chọnVoiceCallLúc bắt đầu và kết thúc của một cuộc gọi đến bot thoại hoặc cuộc gọi do bot thực hiện (chỉ gửi khi yêu cầu theo tên)
voice_call_tool_query tùy chọnVoiceCallToolQueryCông cụ của bot mà mô hình gọi trong cuộc gọi (chỉ gửi khi yêu cầu theo tên)
voice_call_transcript tùy chọnVoiceCallTranscriptMột lượt của bản ghi hội thoại trong cuộc gọi (chỉ gửi khi yêu cầu theo tên)

User

TrườngKiểuMô tả
idIntegerID người dùng (chỉ có nghĩa bên trong máy chủ này)
is_botBooleantrue nếu là bot
first_nameStringTên. Với tài khoản đã bị xóa là Deleted Account
last_name tùy chọnStringHọ
username tùy chọnStringTên người dùng (không có @)

Chat

TrườngKiểuMô tả
idIntegerVới người là ID của người đó (số dương), với nhóm cơ bản là số âm
typeStringprivate hoặc group
title tùy chọnStringTên nhóm (group)
first_name, last_name, username tùy chọnStringTên và tên người dùng của người kia (private)

Message

TrườngKiểuMô tả
message_idIntegerSố hiệu tin nhắn trong cuộc trò chuyện này
from tùy chọnUserNgười gửi
chatChatCuộc trò chuyện chứa tin nhắn
dateIntegerThời điểm gửi (giây Unix)
edit_date tùy chọnIntegerThời điểm sửa gần nhất
text tùy chọnStringNội dung văn bản (luôn có nếu không phải tin nhắn ảnh, tệp, vị trí, địa điểm hay liên hệ)
entities tùy chọnArray of MessageEntityLệnh, lượt nhắc, URL, hashtag trong văn bản
photo tùy chọnArray of PhotoSizeẢnh (Pabal chỉ có một ảnh gốc)
document tùy chọnDocumentTệp
location tùy chọnLocationVị trí hoặc vị trí trực tiếp. Tin nhắn địa điểm cũng kèm vị trí của nó ở đây
venue tùy chọnVenueĐịa điểm
contact tùy chọnContactThẻ liên hệ
caption tùy chọnStringChú thích ảnh
caption_entities tùy chọnArray of MessageEntityLệnh, lượt nhắc, URL, hashtag trong chú thích
reply_markup tùy chọnInlineKeyboardMarkupCác nút inline gắn trên tin nhắn

MessageEntity

TrườngKiểuMô tả
typeStringbot_command, mention, url, hashtag
offsetIntegerVị trí bắt đầu (tính theo đơn vị mã UTF-16)
lengthIntegerĐộ dài (tính theo đơn vị mã UTF-16)

Máy chủ tự tìm trong văn bản và gắn vào. Các entity định dạng như in đậm, in nghiêng hiện chưa có.

PhotoSize

TrườngKiểuMô tả
file_idStringID dùng để tải xuống (getFile) và gửi lại (sendPhoto)
file_unique_idStringCùng một ảnh thì giá trị như nhau dù là bot khác. Không dùng để tải xuống được
width, heightIntegerKích thước tính bằng pixel
file_sizeIntegerByte

Document

TrườngKiểuMô tả
file_idStringID dùng để tải xuống (getFile) và gửi lại (sendDocument)
file_unique_idStringCùng một tệp thì giá trị này giống nhau dù khác bot. Không dùng để tải xuống được
file_nameStringTên do bên gửi đặt
mime_typeStringĐịnh dạng do bên gửi khai báo
file_sizeIntegerByte

Location

TrườngKiểuMô tả
latitude, longitudeFloatVĩ độ và kinh độ
horizontal_accuracy tùy chọnFloatBán kính sai số tính bằng mét
live_period tùy chọnIntegerThời gian chia sẻ của vị trí trực tiếp, tính bằng giây kể từ lúc gửi tin nhắn. Khi dừng, nó được rút ngắn lại còn đúng khoảng thời gian thực sự đã trôi qua
heading tùy chọnIntegerHướng di chuyển, 1–360 độ
proximity_alert_radius tùy chọnIntegerBán kính cảnh báo đến gần tính bằng mét

Vị trí trực tiếp do một người chia sẻ sẽ đến lại dưới dạng edited_message mỗi khi máy chủ áp dụng một lần di chuyển.

Venue

TrườngKiểuMô tả
locationLocationVị trí của địa điểm
titleStringTên địa điểm
addressStringĐịa chỉ
foursquare_id, foursquare_type tùy chọnStringID và loại địa điểm của Foursquare
google_place_id, google_place_type tùy chọnStringID và loại địa điểm của Google

Contact

TrườngKiểuMô tả
phone_numberStringSố điện thoại, đúng như người gửi đã viết
first_nameStringTên
last_name tùy chọnStringHọ
user_id tùy chọnIntegerTài khoản Pabal có số đó. Chỉ có khi người gửi đã lưu người đó trong danh bạ của mình, hoặc chính là người đó
vcard tùy chọnStringThông tin bổ sung ở định dạng vCard

File

TrườngKiểuMô tả
file_id, file_unique_idStringGiống PhotoSize
file_sizeIntegerByte
file_pathStringCó dạng photos/<file_id>.jpg hoặc documents/<file_id>. Ghép vào sau /file/bot<token>/ để tải xuống

CallbackQuery

TrườngKiểuMô tả
idStringID truyền cho answerCallbackQuery
fromUserNgười đã bấm nút
message tùy chọnMessageTin nhắn có gắn nút
chat_instanceStringGiá trị đại diện cho cuộc trò chuyện đó
data tùy chọnStringcallback_data của nút

InlineKeyboardMarkup

inline_keyboard: Array of Array of InlineKeyboardButton — mảng bên ngoài là các hàng, mảng bên trong là các nút của một hàng. Mỗi tin nhắn tối đa 100 hàng và 100 nút.

InlineKeyboardButton

TrườngKiểuMô tả
textStringChữ trên nút
callback_data một trong haiStringGiá trị gửi đến bot khi bấm, 1–64 byte
url một trong haiStringĐịa chỉ mở ra khi bấm

Các loại khác như switch_inline_query, web_app, login_url, pay hiện chưa có (400).

ReplyKeyboardMarkup

TrườngKiểuMô tả
keyboardArray of Array of KeyboardButtonBảng nút bên dưới ô nhập
resize_keyboard, one_time_keyboard, is_persistent, selective tùy chọnBooleanVừa kích thước · ẩn sau một lần dùng · luôn hiển thị · chỉ cho một số người
input_field_placeholder tùy chọnStringChữ gợi ý trong ô nhập

KeyboardButton

Một chuỗi, hoặc một đối tượng có text cùng các trường tùy chọn request_contact (gửi liên hệ của tôi) và request_location (gửi vị trí của tôi, Boolean).

ReplyKeyboardRemove

{"remove_keyboard": true} — ẩn bảng nút. selective là tùy chọn.

ForceReply

{"force_reply": true} — ứng dụng mở ô nhập ở trạng thái trả lời tin nhắn này. selective, input_field_placeholder là tùy chọn.

BotCommand

TrườngKiểuMô tả
commandString1–32 ký tự gồm chữ Latin thường, chữ số, dấu gạch dưới (không có /)
descriptionString1–256 ký tự

WebhookInfo

TrườngKiểuMô tả
urlStringĐịa chỉ webhook, chuỗi rỗng nếu không có
has_custom_certificateBooleanLuôn là false
pending_update_countIntegerSố update đang chờ được chuyển
ip_address tùy chọnStringIP đã gửi đến lần gần nhất
last_error_date tùy chọnIntegerThời điểm thất bại gần nhất (giây Unix)
last_error_message tùy chọnStringLý do thất bại gần nhất (danh sách)
max_connections tùy chọnIntegerGiá trị đã truyền cho setWebhook
allowed_updates tùy chọnArray of StringGiá trị đã truyền cho setWebhook

Cuộc gọi thoại

Đây là các phương thức chỉ Pabal mới có. Bot thoại là bot mà khi có người gọi từ ứng dụng thì một mô hình giọng nói AI trả lời; các phương thức này dùng để đặt cài đặt cho mô hình đó và xử lý cuộc gọi. Những gì cần được bật, cách bật và ví dụ nằm trong hướng dẫn Bot thoại. Các phương thức có sẵn cả trên máy chủ đang tắt tính năng thoại nên bạn vẫn đọc được cài đặt, nhưng khi tính năng thoại tắt hoặc người vận hành chưa cho phép bot, bạn không thể thay đổi cài đặt ngoài việc tắt và xóa (403 VOICE_NOT_AVAILABLE).

setVoiceCallSettings

POST/bot<token>/setVoiceCallSettings

Thay đổi cài đặt thoại của bot. Chỉ những gì được gửi mới thay đổi; toàn bộ được kiểm tra rồi ghi một lần, hoặc bị từ chối toàn bộ. Mỗi bot 30 lần mỗi giờ (tính chung với @BotFather).

Tham sốKiểuBắt buộcMô tả
enabledBooleanTùy chọnChỉ bật được sau khi đã đồng ý quy tắc bot thoại tại @BotFather (403 VOICE_RULES_NOT_ACCEPTED). Tắt thì lúc nào cũng được
instructionsStringTùy chọnChỉ dẫn cho mô hình, tối đa 8.192 byte. "" là xóa (không được với bot ở chế độ managed đang bật)
greetingStringTùy chọnLời chào đầu tiên, tối đa 512 byte. "" thì mô hình tự chào
voiceStringTùy chọnID giọng nói, mặc định kore (danh sách)
languageStringTùy chọnko-KR (mặc định) · en-US · ja-JP · cmn-CN · fr-FR · es-US · id-ID · vi-VN · ar-EG (danh sách). Không phân biệt chữ hoa · chữ thường, và zh-CN được lưu thành cmn-CN. Bot không dùng tiếng Hàn hay tiếng Anh chỉ nhận cuộc gọi sau khi người vận hành đọc chỉ dẫn và lời chào rồi cho phép
max_call_durationIntegerTùy chọnGiây, từ 60 đến limits.max_call_duration
max_concurrent_callsIntegerTùy chọnTừ 1 đến limits.max_concurrent_calls
toolsArray of VoiceCallToolTùy chọnCông cụ của bot mà mô hình gọi trong cuộc gọi: {"name", "description", "parameters"?, "timeout_ms"?}. Quy tắc ở Định nghĩa công cụ. Trong form thì là chuỗi JSON
transcriptBooleanTùy chọnCông tắc bản ghi hội thoại. Chỉ bật được sau khi đồng ý điều khoản chủ bot
modeStringTùy chọnmanaged (mô hình AI của Pabal) hoặc stream (chế độ âm thanh gốc)
stream_url, stream_secretStringTùy chọnĐi cùng mode=stream. Bí mật chỉ gửi trong thân yêu cầu

Trả về: True

getVoiceCallSettings

GET/bot<token>/getVoiceCallSettings

Không có tham số. Cài đặt hiện tại; bot hiện có nhận được cuộc gọi không (available, unavailable_reason); giới hạn của máy chủ; danh sách giọng nói và ngôn ngữ; nơi truy vấn công cụ và bản ghi hội thoại được gửi tới; trạng thái của khóa riêng, chế độ âm thanh gốc và máy chủ MCP. Khóa và bí mật không bao giờ hiện ra, chỉ có dấu vân tay. Các trường được mô tả ở Bot thoại — xem cài đặt hiện tại.

Trả về: VoiceCallSettings (đối tượng)

endVoiceCall

POST/bot<token>/endVoiceCall

Tham sốKiểuBắt buộcMô tả
voice_call_idStringCóvoice_call.id
farewellBooleanTùy chọnMặc định true: mô hình chào tạm biệt ngắn rồi gác máy (nếu sau 10 giây chưa gác thì máy chủ kết thúc). false thì gác ngay

Trả về: True. Nếu không phải cuộc gọi đang diễn ra của bot này thì 400 VOICE_CALL_NOT_FOUND.

sendVoiceCallContext

POST/bot<token>/sendVoiceCallContext

Tham sốKiểuBắt buộcMô tả
voice_call_idStringCóCuộc gọi đang kết nối
textStringCóGhi chú của chủ bot gửi cho mô hình. Tối đa 2.000 ký tự · 6.144 byte, có kiểm tra theo quy tắc nội dung
respondBooleanTùy chọnMặc định false. Nếu true, mô hình phản hồi ngay

Trả về: True. Trước khi kết nối: VOICE_CALL_NOT_ACTIVE; cuộc gọi âm thanh gốc: VOICE_CONTEXT_NOT_SUPPORTED; quá dài: VOICE_CONTEXT_TOO_LONG; quá 10 ghi chú mỗi phút cho một cuộc gọi: 429.

getVoiceCallUsage

GET/bot<token>/getVoiceCallUsage

Tham sốKiểuBắt buộcMô tả
periodStringTùy chọntoday (mặc định) hoặc month
monthStringTùy chọnYYYY-MM, chỉ dùng cùng period=month

Trả về: period, from_date, to_date, calls, seconds, missed, refused (busy·budget·unavailable), platform_seconds, own_key_seconds, remaining_seconds_today (bot·owner), và outbound (today·limits) với bot từng bật gọi đi — mốc ngày theo múi giờ của máy chủ

startVoiceCall

POST/bot<token>/startVoiceCall

Bot gọi cho một người. Chỉ bot được chủ bật trong @BotFather và đã qua người vận hành xét duyệt mới gọi được, và chỉ cho người đã cho phép bot đó. Phản hồi và cách xét yêu cầu có ở Bot thoại — Gọi.

Tham sốKiểuBắt buộcMô tả
user_idIntegerCóNgười cần gọi
purposeStringCóMục đích bot đã chọn trong reminder, wake_up, delivery, appointment
contextStringCóĐiều chỉ mô hình được biết, tới 1.000 ký tự và 3.072 byte, kiểm tra theo quy tắc nội dung
max_durationIntegertùy chọnThời lượng tối đa sau khi nghe máy, tính bằng giây, 30–300 (tới mức trần của bot). Mặc định 180
ring_timeoutIntegertùy chọnSố giây đổ chuông, 30–45. Mặc định 40

Trả về: {"voice_call_id": "…"} — chỉ có nghĩa là yêu cầu đã được nhận; có đổ chuông, có nghe máy hay không tới qua update voice_call. Từ chối: 403 VOICE_OUTBOUND_OFF: <lý do>, 403 USER_UNAVAILABLE (nội dung luôn giống nhau), 429, 503 VOICE_UNAVAILABLE. Không gọi được từ phản hồi webhook.

answerVoiceCallToolQuery

POST/bot<token>/answerVoiceCallToolQuery

Tham sốKiểuBắt buộcMô tả
tool_query_idStringCóid của VoiceCallToolQuery
resultString · Object · ArrayMột trong haiKết quả của công cụ, tối đa 16.384 byte
errorStringMột trong haiCâu báo lỗi của bot, tối đa 512 byte

Trả về: True. Câu trả lời đầu tiên là câu cuối cùng. Nếu muộn thì 400 TOOL_QUERY_EXPIRED: answered|timeout|cancelled|call_ended|unreachable, ID không xác định thì TOOL_QUERY_ID_INVALID, câu trả lời bị từ chối thì TOOL_RESULT_EMPTY·TOOL_RESULT_INVALID·TOOL_RESULT_TOO_LONG·TOOL_ERROR_TOO_LONG·TOOL_RESULT_REFUSED: <mã>. Với POST truy vấn công cụ gửi qua webhook, bạn cũng có thể trả lời ngay trong thân phản hồi.

setVoiceCallApiKey · deleteVoiceCallApiKey

POST/bot<token>/setVoiceCallApiKey

Tham sốKiểuBắt buộcMô tả
providerStringCógoogle (khóa JSON của tài khoản dịch vụ Vertex AI) hoặc openai (sk-…)
api_keyStringCóKhóa. Chỉ gửi trong thân yêu cầu (gửi trong chuỗi truy vấn thì 400), tối đa 8KiB

Trả về: True — chỉ lưu sau khi đã qua phiên thử của gateway. API_KEY_INVALID, API_KEY_NO_REALTIME_ACCESS, 503 API_KEY_CHECK_UNAVAILABLE (không lưu), 403 VOICE_OWN_KEY_NOT_AVAILABLE (máy chủ này không nhận khóa riêng). deleteVoiceCallApiKey không có tham số và luôn trả về True. Cả hai phương thức đều không gọi được qua bots.sendCustomRequest, và setVoiceCallApiKey cũng không gọi được qua phản hồi webhook. Chi tiết ở Khóa mô hình riêng.

Phương thức máy chủ MCP

Phương thứcTham sốTrả về
setVoiceCallMcpServerlabel, url, auth (đối tượng), tùy chọn audience, allowed_tools, requested_level, timeout_ms, tools (ghi đè phân loại), declaration, auto_repinKết quả đăng ký (status, job_id). Nếu nơi nhận thay đổi thì 400 MCP_CHANGE_NEEDS_CONFIRMATION, sau đó xác nhận tại @BotFather
refreshVoiceCallMcpServerlabelKiểm tra lại (refreshing: true, job_id)
deleteVoiceCallMcpServerlabelTrue — được cả khi MCP đang tắt
getVoiceCallMcpBindingKhông cóiss, sub (bot:<id>), issuer_document, jwks_uri, audiences
createVoiceCallMcpClientKeylabeljwk công khai, thumbprint (khóa riêng tư không bao giờ rời khỏi Pabal)

auth và các bí mật chỉ gửi trong thân yêu cầu. Trên máy chủ tắt MCP thì trả về 403 VOICE_NOT_AVAILABLE: MCP tools are not available on this server. Chi tiết ở Bot thoại — máy chủ MCP.

Để nhận update thoại

voice_call, voice_call_tool_query, voice_call_transcript chỉ được gửi khi yêu cầu theo tên — hãy ghi chúng vào allowed_updates của getUpdates hoặc setWebhook. Danh sách rỗng thì không nhận được, và những gì xảy ra trước khi yêu cầu thì không được giữ lại. Truy vấn công cụ được gửi bằng một POST riêng nếu có webhook; nếu bạn đã gọi getUpdates trong 15 giây gần đây thì nó nằm ở đầu lần getUpdates tiếp theo.

VoiceCall

TrườngKiểuMô tả
idStringID cuộc gọi (số thập phân không dấu)
directionStringincoming (cuộc gọi đến bot) hoặc outgoing (cuộc gọi do bot thực hiện). Luôn có
eventStringstarted, ended, missed, refused; với cuộc gọi do bot thực hiện là started, ended, not_answered, failed
from tùy chọnUserChỉ với cuộc gọi đến bot — người gọi: id, is_bot, first_name, last_name, language_code. Không có tên người dùng và số điện thoại
to tùy chọnObjectChỉ với cuộc gọi do bot thực hiện — {"id": …}, chỉ có ID người nhận cuộc gọi
purpose tùy chọnStringChỉ với cuộc gọi do bot thực hiện — mục đích của yêu cầu
dateIntegerThời điểm xảy ra (giây Unix). started là lúc trao đổi khóa xong với cuộc gọi từ ứng dụng, và lúc âm thanh của đồng hồ đã kết nối với cuộc gọi từ Apple Watch. ended đến muộn tối đa 10 giây trên máy chủ chờ bản ghi hội thoại hoặc bật tính năng lưu cuộc trò chuyện. Với cuộc gọi do bot thực hiện, ended của cuộc gọi đã nghe luôn đến muộn tối đa 10 giây, bất kể cài đặt của máy chủ, vì máy chủ chờ mức sử dụng từ gateway
max_duration tùy chọnIntegerĐộ dài tối đa của cuộc gọi này (giây) — started, ended
start_date, duration tùy chọnIntegerThời điểm kết nối và số giây đã kết nối (theo đồng hồ máy chủ) — ended
end_reason tùy chọnStringcaller (callee với cuộc gọi do bot thực hiện), bot, max_length, failed, operator, suspended — ended, missed
refused_reason tùy chọnStringbusy, budget, unavailable — refused
transcript tùy chọnObject{"turns": [{"role", "text", "offset_ms"}], "truncated"} — ended, khi bản ghi hội thoại đang bật. Không bao giờ có ở cuộc gọi do bot thực hiện

VoiceCall không có trường nào cho biết người gọi có chọn lưu cuộc trò chuyện hay không. Đây là chủ ý — văn bản đó thuộc về chính người gọi và không được gửi cho bot. Vì vậy, trên máy chủ bật tính năng lưu cuộc trò chuyện, ended của mọi cuộc gọi không ở chế độ âm thanh gốc đều chờ như nhau, và số của tin nhắn sau nhật ký cuộc gọi luôn lớn hơn số của nhật ký ít nhất 31 ở mọi cuộc gọi (vì các số đã được giữ trước).

VoiceCallToolQuery

TrườngKiểuMô tả
idStringID dùng cho answerVoiceCallToolQuery
voice_call_idStringID cuộc gọi
fromUserNgười gọi (các trường giống VoiceCall)
nameStringTên công cụ
argumentsStringĐối số, là văn bản của một đối tượng JSON (máy chủ đã kiểm tra)
budget_msIntegerSố mili giây tính từ lúc nhận đến lúc câu trả lời phải tới máy chủ

VoiceCallTranscript

TrườngKiểuMô tả
voice_call_idStringID cuộc gọi
seqIntegerSố thứ tự lượt
roleStringcaller hoặc bot
textStringVăn bản do AI ghi lại. Nếu có số thẻ hay số định danh cá nhân thì các chữ số được thay bằng *
is_finalBooleanLuôn là true
offset_ms, dateIntegerSố mili giây tính từ lúc âm thanh cuộc gọi bắt đầu, và thời điểm

Chỉ được gửi qua HTTP Bot API. Toàn bộ cuộc gọi nằm trong transcript của voice_call khi kết thúc.

Chế độ âm thanh gốc (mode=stream)

Ở chế độ âm thanh gốc, âm thanh cuộc gọi được gửi tới máy chủ của chủ bot thay cho mô hình AI của Pabal. Khi bạn gửi mode=stream, stream_url=wss://…, stream_secret=… (32–128 ký tự ASCII in được, chỉ trong thân yêu cầu) cho setVoiceCallSettings, gateway của Pabal thử kết nối tới địa chỉ đó một lần (thăm dò) và bật chế độ nếu thành công. Cần có điều khoản chủ bot và bản build ứng dụng có màn hình xác nhận âm thanh gốc. Cài đặt, kết quả thăm dò và ví dụ nằm ở Bot thoại — chế độ âm thanh gốc.

  • Kết nối: TLS 1.2 trở lên, chứng chỉ công khai khớp với tên trong URL, subprotocol pabal.voice.v1, không nén, mỗi thông điệp tối đa 64KiB · văn bản tối đa 4KiB, không chuyển hướng.
  • Chữ ký: 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 là host của URL mà bạn đã khai báo. Kiểm tra 300 giây · mỗi nonce một lần · so sánh theo byte · start.call_id có bằng call hay không (chi tiết).
  • Âm thanh: thông điệp văn bản là sự kiện JSON, thông điệp nhị phân là PCM16 little-endian · mono · 24 kHz. Âm thanh của người gọi là các mảnh 20 ms (960 byte).
  • Pabal → bot: start (một lần) · live (thông báo AI đã phát xong) · âm thanh · mark · cleared · buffer_full · stop (→ đóng 1000).
  • Bot → Pabal: ready (trong vòng 3 giây sau start, trước mọi thứ khác) · âm thanh (sau live) · clear · mark · hangup.

Hình dạng của từng thông điệp nằm trong bảng ở Bot thoại — đặc tả.

Lỗi của phương thức thoại

Mã lỗi và ý nghĩa của các phương thức thoại được tập hợp ở Bot thoại — lỗi. Lỗi 403 có dạng Forbidden: <mã>: <mô tả> (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 luôn đúng là Forbidden: USER_UNAVAILABLE, không có mô tả; và khi vượt giới hạn theo giờ thì là 429 kèm retry_after.

Khác biệt so với Telegram Bot API

  • Loại update: chỉ có message, edited_message, callback_query và các loại của bot thoại chỉ Pabal mới có (voice_call, voice_call_tool_query, voice_call_transcript). Không có bài đăng kênh, truy vấn inline, thanh toán, bình chọn, thay đổi thành viên (my_chat_member)…
  • Định dạng: bỏ qua parse_mode và entities, gửi nguyên văn. Chỉ lệnh, lượt nhắc, URL và hashtag được đánh dấu tự động.
  • Loại cuộc trò chuyện: chỉ có 1:1 và nhóm cơ bản. Không có kênh, siêu nhóm, chủ đề diễn đàn.
  • Phương tiện: chỉ có ảnh, tệp (sendDocument), vị trí, vị trí trực tiếp, địa điểm và liên hệ. Không có tin nhắn phát dưới dạng video hay âm thanh, sticker, album (sendMediaGroup), bình chọn, cũng như gửi bằng URL. Tệp tải lên và tải xuống qua HTTP tối đa 20MB.
  • Vị trí: cảnh báo đến gần của vị trí trực tiếp (proximity_alert_radius) chỉ được lưu, không bao giờ được gửi. Các lần di chuyển trong vòng 10 giây hoặc 10 m sẽ bị bỏ qua mà không áp dụng, và thẻ liên hệ do bot gửi không kèm user_id.
  • Bot trong nhóm: không có chế độ riêng tư, nên bot nhận mọi tin nhắn của nhóm.
  • Hàng đợi: update chưa lấy được giữ trong bộ nhớ, tối đa 1.000 update gần nhất cho mỗi bot, và mất khi máy chủ khởi động lại (Telegram giữ 24 giờ).
  • Webhook: gửi lần lượt từng update theo thứ tự (max_connections chỉ được lưu lại), không nhận chứng chỉ tự ký, không giới hạn cổng.
  • ID: ID người dùng, tin nhắn và tệp chỉ có nghĩa bên trong máy chủ này. Vì không có kênh và siêu nhóm nên cũng không có ID dạng -100….
  • Phương thức không có: những phương thức không có trong danh sách trên (forwardMessage, copyMessage, sendVideo, sendPoll, getChatMember, banChatMember, answerInlineQuery …) đều trả về 404 Not Found: method not found.