Docs développeurs
Français

Développement de bots

Référence de la Bot API

Toutes les méthodes acceptées par la Bot API HTTP de Pabal, les objets échangés et les erreurs, sans exception. Compatible avec la Bot API de Telegram.

La Bot API HTTP de Pabal utilise le même format d'adresse, de requêtes, de réponses et d'erreurs que la Bot API de Telegram. Cette page ne décrit que ce que Pabal accepte réellement. Une méthode qui n'y figure pas renvoie 404 Not Found: method not found. Si vous débutez, commencez par le tutoriel de création de bot.

Envoyer une requête

https://pabal.me/bot<jeton>/<méthode>
  • Méthode HTTP : GET et POST fonctionnent tous les deux.
  • Quatre façons d'envoyer les paramètres : chaîne de requête (?chat_id=1&text=hi), application/x-www-form-urlencoded, application/json, et multipart/form-data pour envoyer des fichiers. Vous pouvez les combiner.
  • Les paramètres de type objet (reply_markup, commands, allowed_updates) se passent tels quels (objet ou tableau) dans un corps JSON, et sous forme de chaîne JSON dans un formulaire ou une chaîne de requête.
  • Les noms de méthode ne tiennent pas compte de la casse (sendMessage = sendmessage).
  • La taille du corps est limitée à 12 Mo (au-delà : 413).
  • Le téléchargement de fichiers se fait à part, via https://pabal.me/file/bot<jeton>/<file_path> (getFile).

Réponses et erreurs

La réponse est toujours du JSON. En cas de succès : HTTP 200 et result ; en cas d'échec : un error_code égal au statut HTTP et une description lisible par un humain.

{"ok": true, "result": { … }}
{"ok": false, "error_code": 400, "description": "Bad Request: chat not found"}
error_codeQuandExemples de description
400Paramètre incorrectBad 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
401Jeton incorrectUnauthorized
403Pas le droit d'envoyerForbidden: bot can't initiate conversation with a user, Forbidden: bot is not a member of the group chat
404Méthode ou fichier inexistantNot Found: method not found
409getUpdates alors qu'un webhook est configuréConflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first
413Corps de plus de 12 MoRequest Entity Too Large
500Erreur interne du serveurInternal Server Error

Pabal n'impose pas encore de limite de débit sur l'ensemble des requêtes, mais les méthodes vocales ont une limite horaire et peuvent renvoyer 429 Too Many Requests: retry after N (Appels vocaux). Prévoyez qu'en cas de 429, votre code attende parameters.retry_after secondes avant de renvoyer la requête.

Recevoir les mises à jour

Utilisez l'une des deux méthodes. Il est impossible d'utiliser les deux en même temps.

getUpdates

POST/bot<jeton>/getUpdates

Récupère les mises à jour en attente (long polling). Si un webhook est configuré : 409.

ParamètreTypeObligatoireDescription
offsetIntegerFacultatifSeulement les mises à jour de ce numéro ou au-delà. Les précédentes sont effacées comme « reçues ». Passez le dernier update_id + 1 traité.
limitIntegerFacultatif1 à 100, 100 par défaut
timeoutIntegerFacultatifSecondes d'attente, de 0 à 50, 0 par défaut. Une valeur de 25 à 30 est recommandée.
allowed_updatesArray of StringFacultatifTypes à recevoir (Update). Vide : tous les types par défaut (message, edited_message, callback_query). Les types vocaux n'arrivent que si vous les nommez. La liste donnée reste enregistrée comme réglage du bot et sert aussi aux appels suivants et au webhook (si vous n'en donnez pas, la valeur précédente est conservée)

Renvoie : Array of Update

setWebhook

POST/bot<jeton>/setWebhook

Reçoit les mises à jour sur une adresse HTTPS. Tous les détails sont dans la page Webhooks.

ParamètreTypeObligatoireDescription
urlStringOuiAdresse publique https://. Une chaîne vide supprime le webhook
secret_tokenStringFacultatif1 à 256 caractères, A-Z a-z 0-9 _ -. Envoyé dans l'en-tête de requête X-Telegram-Bot-Api-Secret-Token
allowed_updatesArray of StringFacultatifParmi message, edited_message, callback_query. Si la liste est vide : ces trois types. Les types vocaux (voice_call, voice_call_tool_query, voice_call_transcript) n'arrivent que si vous les nommez. Si vous n'en donnez pas, la valeur précédente est conservée
drop_pending_updatesBooleanFacultatifJette les mises à jour en attente
max_connectionsIntegerFacultatif1 à 100, 40 par défaut. Seulement conservé : la livraison se fait une requête à la fois par bot
certificateInputFileNon pris en charge400 — utilisez un certificat public
ip_addressStringIgnoré

Renvoie : True

deleteWebhook

POST/bot<jeton>/deleteWebhook

Supprime le webhook et revient à getUpdates. Réussit même s'il n'y a pas de webhook.

ParamètreTypeObligatoireDescription
drop_pending_updatesBooleanFacultatifJette les mises à jour en attente

Renvoie : True

getWebhookInfo

GET/bot<jeton>/getWebhookInfo

État du webhook. Aucun paramètre. S'il n'y a pas de webhook, url est une chaîne vide.

Renvoie : WebhookInfo

Méthodes

MéthodeCe qu'elle fait
getMeInformations sur le bot lui-même
sendMessageEnvoyer un texte (boutons compris)
sendPhotoEnvoyer une photo
sendDocumentEnvoyer un fichier
sendLocationEnvoyer une position (y compris en direct)
sendVenueEnvoyer un lieu (une position avec un nom et une adresse)
sendContactEnvoyer une fiche de contact
editMessageLiveLocation · stopMessageLiveLocationDéplacer ou arrêter une position en direct
editMessageTextModifier le texte et les boutons d'un message envoyé
editMessageCaptionModifier la légende d'une photo
editMessageReplyMarkupModifier seulement les boutons
deleteMessageSupprimer un message
answerCallbackQueryRépondre à un appui sur un bouton
sendChatActionIndicateur « en train d'écrire » (seulement accepté)
getChatInformations sur une conversation
getFileChemin de téléchargement d'une photo reçue
setMyCommands · getMyCommands · deleteMyCommandsMenu des commandes
logOut · closePour compatibilité (ne font rien)
getUpdates · setWebhook · deleteWebhook · getWebhookInfoRecevoir les mises à jour (ci-dessus)
setVoiceCallSettings · getVoiceCallSettings · endVoiceCall · sendVoiceCallContext · getVoiceCallUsage · startVoiceCall · answerVoiceCallToolQuery · setVoiceCallApiKey · setVoiceCallMcpServer …Bots vocaux (voir Appels vocaux ci-dessous)
Ce que vous pouvez passer dans chat_id

Pour une conversation 1:1, l'ID de la personne (positif) ; pour un groupe simple, l'ID du groupe (négatif) ; ou encore le nom d'utilisateur de la personne ("@hana_lee"). Toutes ces valeurs se retrouvent dans le chat.id des mises à jour. Les ID de canaux et de supergroupes (-100…) n'existent pas encore (400 chat not found).

getMe

GET/bot<jeton>/getMe

Sert à vérifier que le jeton est correct. Aucun paramètre.

Renvoie : User — pour un bot, s'y ajoutent can_join_groups (true), can_read_all_group_messages (true), supports_inline_queries (false), can_connect_to_business (false) et has_main_web_app (false).

sendMessage

POST/bot<jeton>/sendMessage

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation de destination (voir l'encadré ci-dessus)
textStringOui1 à 4 096 caractères. Envoyé tel quel
reply_markupInlineKeyboardMarkup · ReplyKeyboardMarkup · ReplyKeyboardRemove · ForceReplyFacultatifBoutons
disable_notificationBooleanFacultatifEnvoyer sans son
parse_mode, entities, reply_parameters, link_preview_options …IgnoréAcceptés mais non utilisés. Aucune mise en forme n'est appliquée

Renvoie : le Message envoyé

Pour écrire à une personne, il faut que celle-ci ait écrit au bot en premier (403 Forbidden: bot can't initiate conversation with a user). Pour écrire dans un groupe, le bot doit être membre de ce groupe.

sendPhoto

POST/bot<jeton>/sendPhoto

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation de destination
photoInputFile ou StringOuiFichier envoyé en multipart/form-data (10 Mo maximum, JPEG, PNG ou GIF), ou file_id d'une photo reçue auparavant. Pas encore d'URL
captionStringFacultatif0 à 1 024 caractères
reply_markupComme pour sendMessageFacultatif
disable_notificationBooleanFacultatif

Renvoie : le Message envoyé (avec un nouveau file_id dans photo)

sendDocument

POST/bot<jeton>/sendDocument

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation de destination
documentInputFile ou StringOuiFichier envoyé en multipart/form-data (tous formats, 20 Mo maximum), ou file_id d'un fichier reçu auparavant. Pas encore d'URL
filenameStringFacultatifNom affiché chez le destinataire. À défaut, celui du fichier envoyé est utilisé
captionStringFacultatif0 à 1 024 caractères
reply_markupComme pour sendMessageFacultatif
disable_notificationBooleanFacultatif
thumbnail, disable_content_type_detectionIgnoréAcceptés mais non utilisés

Renvoie : le Message envoyé (avec un nouveau file_id dans document)

Le format (mime_type) est déduit de l'extension du nom de fichier. Un fichier envoyé depuis une application peut atteindre 2 Go, mais ce qu'un bot téléverse ou télécharge en HTTP est limité à 20 Mo, comme chez Telegram.

sendLocation

POST/bot<jeton>/sendLocation

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation de destination
latitude, longitudeFloatOuiLatitude (−90 à 90) et longitude (−180 à 180). Hors limites : 400 Bad Request: GEO_POINT_INVALID
horizontal_accuracyFloatFacultatifRayon d'incertitude en mètres, de 0 à 1 500. Arrondi à l'entier lors de l'enregistrement
live_periodIntegerFacultatifEn fait une position en direct : 60 à 86 400 secondes, ou 2147483647 (0x7FFFFFFF) jusqu'à l'arrêt. Toute autre valeur donne 400 Bad Request: wrong live_period
headingIntegerFacultatifDirection de déplacement d'une position en direct, 1 à 360 degrés
proximity_alert_radiusIntegerFacultatifRayon de l'alerte de proximité d'une position en direct, en mètres. Enregistré et affiché, mais aucune alerte n'est encore envoyée
reply_markupComme pour sendMessageFacultatif
disable_notificationBooleanFacultatif

Renvoie : le Message envoyé (avec une Location dans location)

sendVenue

POST/bot<jeton>/sendVenue

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation de destination
latitude, longitudeFloatOuiEmplacement du lieu (comme pour sendLocation)
titleStringOuiNom du lieu
addressStringOuiAdresse
foursquare_id, foursquare_typeStringFacultatifIdentifiant et type du lieu chez Foursquare, transmis tels quels
google_place_id, google_place_typeStringFacultatifIdentifiant et type du lieu chez Google. Utilisés seulement en l'absence de foursquare_id
reply_markupComme pour sendMessageFacultatif
disable_notificationBooleanFacultatif

Renvoie : le Message envoyé (avec un Venue dans venue, et le même point dans location)

Sans title ou address : 400 Bad Request: title and address are required.

sendContact

POST/bot<jeton>/sendContact

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation de destination
phone_numberStringOuiNuméro de téléphone, transmis tel qu'il est écrit
first_nameStringOuiPrénom
last_nameStringFacultatifNom de famille
vcardStringFacultatifInformations supplémentaires au format vCard, jusqu'à 64 Ko
reply_markupComme pour sendMessageFacultatif
disable_notificationBooleanFacultatif

Renvoie : le Message envoyé (avec un Contact dans contact)

Une fiche de contact envoyée par un bot ne porte jamais de user_id, même quand le numéro appartient à un compte Pabal — un bot n'a pas de contacts, et renseigner ce champ lui permettrait de découvrir à qui appartient un numéro en envoyant une fiche par numéro. Sans phone_number ou first_name : 400 Bad Request: phone_number and first_name are required.

editMessageLiveLocation

POST/bot<jeton>/editMessageLiveLocation

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation contenant le message
message_idIntegerOuiPosition en direct à déplacer (envoyée par le bot)
latitude, longitudeFloatOuiNouvelle position
horizontal_accuracyFloatFacultatifRayon d'incertitude en mètres, de 0 à 1 500
headingIntegerFacultatifDirection de déplacement, 1 à 360 degrés
proximity_alert_radiusIntegerFacultatifRayon de l'alerte de proximité en mètres. 0 la désactive
live_periodIntegerFacultatifNouvelle durée de partage, en secondes comptées depuis l'envoi du message. Elle ne peut pas dépasser la durée actuelle de plus d'un jour ; 2147483647 signifie jusqu'à l'arrêt
reply_markupInlineKeyboardMarkupFacultatifNouveaux boutons
inline_message_idStringNon pris en charge400, car le mode inline n'existe pas

Renvoie : le Message modifié

Une position en direct déjà terminée — arrêtée, ou dont la durée est écoulée — ne peut plus être déplacée ni ranimée en prolongeant sa durée (400 Bad Request: message can't be edited). Il en va de même pour un message qui n'est pas une position en direct.

Un déplacement effectué moins de 10 secondes après le dernier déplacement pris en compte, ou de moins de 10 m, est laissé de côté sans être enregistré. L'arrêt et un changement de durée ou de rayon d'alerte sont toujours pris en compte. Quand un déplacement est laissé de côté, le Message renvoyé montre la dernière position prise en compte : vous pouvez donc envoyer des déplacements toutes les quelques secondes.

stopMessageLiveLocation

POST/bot<jeton>/stopMessageLiveLocation

Paramètres : chat_id, message_id, reply_markup (facultatif). Arrête la position en direct là où elle se trouvait en dernier. Sa durée de partage est ramenée au temps réellement écoulé, si bien que toutes les applications l'affichent comme terminée. Si elle est déjà arrêtée ou terminée : 400 Bad Request: message is not modified: …. Renvoie : le Message modifié.

editMessageText

POST/bot<jeton>/editMessageText

ParamètreTypeObligatoireDescription
chat_idInteger ou StringOuiConversation contenant le message
message_idIntegerOuiMessage à modifier (envoyé par le bot)
textStringOuiNouveau texte, 1 à 4 096 caractères
reply_markupInlineKeyboardMarkupFacultatifNouveaux boutons. Sans ce paramètre, les boutons disparaissent (comme chez Telegram)
inline_message_idStringNon pris en charge400, car le mode inline n'existe pas

Renvoie : le Message modifié. La modification apparaît aussitôt dans l'application ; un message modifié par une personne arrive au bot sous forme d'edited_message.

Si le texte et les boutons sont identiques à avant : 400 Bad Request: message is not modified: … ; si vous tentez de modifier le message de quelqu'un d'autre : 400 Bad Request: message can't be edited.

editMessageCaption

POST/bot<jeton>/editMessageCaption

Paramètres : chat_id, message_id, caption (0 à 1 024 caractères ; sans ce paramètre, la légende est supprimée), reply_markup. Renvoie : le Message modifié.

editMessageReplyMarkup

POST/bot<jeton>/editMessageReplyMarkup

Change seulement les boutons, sans toucher au texte. Paramètres : chat_id, message_id, reply_markup (sans ce paramètre, les boutons sont supprimés). Renvoie : le Message modifié.

deleteMessage

POST/bot<jeton>/deleteMessage

Paramètres : chat_id, message_id. Supprime le message des deux côtés de la conversation. Si le message n'existe pas : 400 Bad Request: message to delete not found. Renvoie : True.

answerCallbackQuery

POST/bot<jeton>/answerCallbackQuery

Répond au bouton sur lequel une personne a appuyé (CallbackQuery). On ne peut répondre que dans les 10 secondes, et une seule fois.

ParamètreTypeObligatoireDescription
callback_query_idStringOuiLe callback_query.id de la mise à jour
textStringFacultatifTexte affiché brièvement en haut de l'écran
show_alertBooleanFacultatifSi true, une fenêtre avec un bouton de confirmation
urlStringFacultatifAdresse que l'application doit ouvrir
cache_timeIntegerFacultatifDurée en secondes pendant laquelle l'application mémorise cette réponse

Renvoie : True. S'il est trop tard ou si une réponse a déjà été donnée : 400 Bad Request: query is too old and response timeout expired or query ID is invalid.

sendChatAction

POST/bot<jeton>/sendChatAction

Acceptée par souci de compatibilité, elle renvoie True, mais n'affiche pas encore « en train d'écrire… » dans l'application.

getChat

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

Paramètre : chat_id (nombre). Pour une personne, cette personne ; pour un groupe, uniquement un groupe dont le bot est membre. Renvoie : Chat. Inexistant ou non visible : 400 Bad Request: chat not found.

getFile

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

Obtient le chemin de téléchargement à partir du file_id d'une photo reçue. Renvoie : File. Téléchargez ensuite à cette adresse :

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

Le file_id vaut aussi autorisation de récupérer cette photo. Valeur incorrecte : 400 Bad Request: wrong file identifier/HTTP URL specified.

setMyCommands

POST/bot<jeton>/setMyCommands

ParamètreTypeObligatoireDescription
commandsArray of BotCommandOui100 au maximum
language_codeStringFacultatifEnregistré comme liste propre à cette langue. L'application n'affiche pour l'instant que la liste par défaut, sans code de langue
scopeBotCommandScopeIgnoré

Renvoie : True. Si le menu ne respecte pas les règles, rien n'est enregistré : 400 Bad Request: BOT_COMMAND_INVALID (une commande), BOT_COMMAND_DESCRIPTION_INVALID (une description vide ou de plus de 256 caractères), BOT_COMMANDS_TOO_MUCH (plus de 100).

getMyCommands

GET/bot<jeton>/getMyCommands

Paramètre : language_code (facultatif). Renvoie : Array of BotCommand.

deleteMyCommands

POST/bot<jeton>/deleteMyCommands

Paramètre : language_code (facultatif). Vide la liste correspondante. Renvoie : True.

logOut · close

Chez Telegram, ces méthodes servent à migrer vers un serveur Bot API local. Pabal n'ayant nulle part où migrer, il les accepte simplement et renvoie True. Pour invalider un jeton, utilisez /revoke auprès de BotFather.

Objets

La mention facultatif à côté d'un champ signifie qu'il peut être absent. Les autres champs de Telegram qui ne figurent pas ici ne sont pas envoyés par Pabal.

Update

Une mise à jour. Contient update_id et un seul des champs ci-dessous.

ChampTypeDescription
update_idIntegerNuméro qui augmente de 1. Sert d'offset pour getUpdates
message facultatifMessageNouveau message adressé au bot (en 1:1, ou tous les messages d'un groupe dont le bot est membre)
edited_message facultatifMessageMessage modifié
callback_query facultatifCallbackQueryAppui sur un bouton inline
voice_call facultatifVoiceCallDébut et fin d'un appel à un bot vocal ou d'un appel qu'il a passé (n'arrive que si on le demande par son nom)
voice_call_tool_query facultatifVoiceCallToolQueryOutil du bot appelé par le modèle pendant l'appel (n'arrive que si on le demande par son nom)
voice_call_transcript facultatifVoiceCallTranscriptUn tour de parole de la transcription pendant l'appel (n'arrive que si on le demande par son nom)

User

ChampTypeDescription
idIntegerID d'utilisateur (n'a de sens que sur ce serveur)
is_botBooleantrue pour un bot
first_nameStringPrénom. Deleted Account pour un compte supprimé
last_name facultatifStringNom de famille
username facultatifStringNom d'utilisateur (sans @)

Chat

ChampTypeDescription
idIntegerPour une personne, son ID (positif) ; pour un groupe simple, un nombre négatif
typeStringprivate ou group
title facultatifStringNom du groupe (group)
first_name, last_name, username facultatifStringNom et nom d'utilisateur de l'interlocuteur (private)

Message

ChampTypeDescription
message_idIntegerNuméro du message dans cette conversation
from facultatifUserExpéditeur
chatChatConversation contenant le message
dateIntegerHeure d'envoi (secondes Unix)
edit_date facultatifIntegerHeure de la dernière modification
text facultatifStringTexte (toujours présent, sauf pour un message photo, fichier, position, lieu ou contact)
entities facultatifArray of MessageEntityCommandes, mentions, URL et hashtags du texte
photo facultatifArray of PhotoSizePhoto (chez Pabal, l'original seul)
document facultatifDocumentFichier
location facultatifLocationPosition ou position en direct. Un message de lieu porte aussi sa position ici
venue facultatifVenueLieu
contact facultatifContactFiche de contact
caption facultatifStringLégende de la photo
caption_entities facultatifArray of MessageEntityCommandes, mentions, URL et hashtags de la légende
reply_markup facultatifInlineKeyboardMarkupBoutons inline attachés au message

MessageEntity

ChampTypeDescription
typeStringbot_command, mention, url, hashtag
offsetIntegerPosition de début (en unités de code UTF-16)
lengthIntegerLongueur (en unités de code UTF-16)

Le serveur les détecte et les ajoute automatiquement à partir du texte. Les entités de mise en forme comme le gras ou l'italique n'existent pas encore.

PhotoSize

ChampTypeDescription
file_idStringID utilisé pour télécharger (getFile) et pour renvoyer (sendPhoto)
file_unique_idStringMême valeur pour une même photo, même d'un bot à l'autre. Inutilisable pour télécharger
width, heightIntegerDimensions en pixels
file_sizeIntegerOctets

Document

ChampTypeDescription
file_idStringID utilisé pour télécharger (getFile) et pour renvoyer (sendDocument)
file_unique_idStringMême valeur pour un même fichier, même d'un bot à l'autre. Inutilisable pour télécharger
file_nameStringNom donné par l'expéditeur
mime_typeStringFormat annoncé par l'expéditeur
file_sizeIntegerOctets

Location

ChampTypeDescription
latitude, longitudeFloatLatitude et longitude
horizontal_accuracy facultatifFloatRayon d'incertitude en mètres
live_period facultatifIntegerDurée de partage d'une position en direct, en secondes comptées depuis l'envoi du message. Une fois arrêtée, elle est ramenée au temps réellement écoulé
heading facultatifIntegerDirection de déplacement, 1 à 360 degrés
proximity_alert_radius facultatifIntegerRayon de l'alerte de proximité en mètres

Une position en direct partagée par une personne arrive de nouveau sous forme d'edited_message chaque fois que le serveur prend en compte un déplacement.

Venue

ChampTypeDescription
locationLocationEmplacement du lieu
titleStringNom du lieu
addressStringAdresse
foursquare_id, foursquare_type facultatifStringIdentifiant et type du lieu chez Foursquare
google_place_id, google_place_type facultatifStringIdentifiant et type du lieu chez Google

Contact

ChampTypeDescription
phone_numberStringLe numéro, tel que l'expéditeur l'a écrit
first_nameStringPrénom
last_name facultatifStringNom de famille
user_id facultatifIntegerLe compte Pabal qui a ce numéro. Présent seulement si l'expéditeur a enregistré cette personne dans ses contacts, ou s'il s'agit de lui-même
vcard facultatifStringInformations supplémentaires au format vCard

File

ChampTypeDescription
file_id, file_unique_idStringComme pour PhotoSize
file_sizeIntegerOctets
file_pathStringDe la forme photos/<file_id>.jpg ou documents/<file_id>. À ajouter après /file/bot<jeton>/ pour télécharger

CallbackQuery

ChampTypeDescription
idStringID à passer à answerCallbackQuery
fromUserPersonne qui a appuyé sur le bouton
message facultatifMessageMessage portant le bouton
chat_instanceStringValeur représentant cette conversation
data facultatifStringLe callback_data du bouton

InlineKeyboardMarkup

inline_keyboard : Array of Array of InlineKeyboardButton — le tableau externe contient les rangées, chaque tableau interne les boutons d'une rangée. Au maximum 100 rangées et 100 boutons par message.

InlineKeyboardButton

ChampTypeDescription
textStringTexte du bouton
callback_data l'un des deuxStringValeur envoyée au bot quand on appuie, 1 à 64 octets
url l'un des deuxStringAdresse ouverte quand on appuie

Les autres types, comme switch_inline_query, web_app, login_url ou pay, n'existent pas encore (400).

ReplyKeyboardMarkup

ChampTypeDescription
keyboardArray of Array of KeyboardButtonPavé de boutons sous le champ de saisie
resize_keyboard, one_time_keyboard, is_persistent, selective facultatifBooleanAjuster la taille · masquer après usage · toujours visible · seulement pour certaines personnes
input_field_placeholder facultatifStringTexte indicatif dans le champ de saisie

KeyboardButton

Une simple chaîne, ou un objet avec text et les champs facultatifs request_contact (envoyer mon contact) et request_location (envoyer ma position), de type Boolean.

ReplyKeyboardRemove

{"remove_keyboard": true} — masque le pavé de boutons. selective facultatif.

ForceReply

{"force_reply": true} — l'application ouvre le champ de saisie en mode réponse à ce message. selective et input_field_placeholder facultatifs.

BotCommand

ChampTypeDescription
commandString1 à 32 caractères : minuscules latines, chiffres, tiret bas (sans /)
descriptionString1 à 256 caractères

WebhookInfo

ChampTypeDescription
urlStringAdresse du webhook, chaîne vide s'il n'y en a pas
has_custom_certificateBooleanToujours false
pending_update_countIntegerNombre de mises à jour en attente de livraison
ip_address facultatifStringDernière IP vers laquelle un envoi a eu lieu
last_error_date facultatifIntegerHeure du dernier échec (secondes Unix)
last_error_message facultatifStringRaison du dernier échec (liste)
max_connections facultatifIntegerValeur passée à setWebhook
allowed_updates facultatifArray of StringValeur passée à setWebhook

Appels vocaux

Ces méthodes n'existent que dans Pabal. Un bot vocal est un bot que l'on appelle depuis l'application et dont les appels sont pris par un modèle vocal d'IA ; ces méthodes servent à régler ce modèle et à gérer les appels. Ce qui doit être activé, la façon d'activer et des exemples se trouvent dans le guide Bots vocaux. Les méthodes existent aussi sur un serveur où la voix est désactivée, ce qui permet de lire les réglages, mais un bot dont la voix est désactivée ou que l'opérateur n'a pas encore autorisé ne peut modifier ses réglages que pour désactiver ou effacer (403 VOICE_NOT_AVAILABLE).

setVoiceCallSettings

POST/bot<jeton>/setVoiceCallSettings

Modifie les réglages vocaux du bot. Seul ce que vous envoyez change ; le serveur vérifie l'ensemble puis écrit tout d'un coup, ou refuse tout. 30 fois par heure et par bot (en comptant @BotFather).

ParamètreTypeObligatoireDescription
enabledBooleanFacultatifActiver n'est possible qu'après avoir accepté les règles des bots vocaux dans @BotFather (403 VOICE_RULES_NOT_ACCEPTED). Désactiver est toujours possible
instructionsStringFacultatifInstructions du modèle, jusqu'à 8 192 octets. "" les efface (impossible pour un bot géré activé)
greetingStringFacultatifMessage d'accueil, jusqu'à 512 octets. Avec "", le modèle s'en charge
voiceStringFacultatifIdentifiant de voix, kore par défaut (liste)
languageStringFacultatifko-KR (par défaut) · en-US · ja-JP · cmn-CN · fr-FR · es-US · id-ID · vi-VN · ar-EG (liste). La casse n'est pas prise en compte, et zh-CN est enregistré sous la forme cmn-CN. Un bot dans une autre langue que le coréen et l'anglais ne prend des appels qu'une fois que l'opérateur a lu et autorisé ses instructions et son message d'accueil
max_call_durationIntegerFacultatifSecondes, de 60 à limits.max_call_duration
max_concurrent_callsIntegerFacultatifDe 1 à limits.max_concurrent_calls
toolsArray of VoiceCallToolFacultatifOutils du bot que le modèle peut appeler pendant l'appel : {"name", "description", "parameters"?, "timeout_ms"?}. Règles dans Définir des outils. Dans un formulaire, une chaîne JSON
transcriptBooleanFacultatifInterrupteur de la transcription. L'activer exige les conditions du propriétaire de bot
modeStringFacultatifmanaged (le modèle d'IA de Pabal) ou stream (mode flux)
stream_url, stream_secretStringFacultatifAvec mode=stream. Le secret uniquement dans le corps de la requête

Renvoie : True

getVoiceCallSettings

GET/bot<jeton>/getVoiceCallSettings

Sans paramètre. Les réglages actuels ; si le bot peut prendre des appels en ce moment (available, unavailable_reason) ; les limites du serveur ; la liste des voix et des langues ; où iraient les requêtes d'outil et la transcription ; l'état de la clé propre, du mode flux et des serveurs MCP. Les clés et les secrets n'apparaissent jamais, seulement leurs empreintes. Les champs sont décrits dans Bots vocaux — Voir les réglages actuels.

Renvoie : VoiceCallSettings (objet)

endVoiceCall

POST/bot<jeton>/endVoiceCall

ParamètreTypeObligatoireDescription
voice_call_idStringOuivoice_call.id
farewellBooleanFacultatiftrue par défaut : le modèle dit un court au revoir puis raccroche (si ce n'est pas terminé au bout de 10 secondes, le serveur y met fin). false : coupe tout de suite

Renvoie : True. Si ce n'est pas un appel en cours de ce bot : 400 VOICE_CALL_NOT_FOUND.

sendVoiceCallContext

POST/bot<jeton>/sendVoiceCallContext

ParamètreTypeObligatoireDescription
voice_call_idStringOuiUn appel établi
textStringOuiNote du propriétaire du bot pour le modèle. Jusqu'à 2 000 caractères et 6 144 octets, soumise aux règles de contenu
respondBooleanFacultatiffalse par défaut. true : le modèle réagit aussitôt

Renvoie : True. Avant la connexion : VOICE_CALL_NOT_ACTIVE ; appel en mode flux : VOICE_CONTEXT_NOT_SUPPORTED ; trop long : VOICE_CONTEXT_TOO_LONG ; plus de 10 par minute et par appel : 429.

getVoiceCallUsage

GET/bot<jeton>/getVoiceCallUsage

ParamètreTypeObligatoireDescription
periodStringFacultatiftoday (par défaut) ou month
monthStringFacultatifYYYY-MM, seulement avec period=month

Renvoie : period, from_date, to_date, calls, seconds, missed, refused (busy·budget·unavailable), platform_seconds, own_key_seconds, remaining_seconds_today (bot·owner), et outbound (today·limits) pour un bot qui a déjà activé les appels — les limites de dates suivent le fuseau horaire du serveur

startVoiceCall

POST/bot<jeton>/startVoiceCall

Le bot appelle une personne. Seul un bot dont le propriétaire a activé cette fonction dans @BotFather et que l'opérateur a examiné peut appeler, et seulement les personnes qui l'ont autorisé. Les réponses et l'examen des demandes sont décrits dans Bots vocaux — Appeler.

ParamètreTypeObligatoireDescription
user_idIntegerOuiLa personne à appeler
purposeStringOuiCelui que le bot a choisi parmi reminder, wake_up, delivery, appointment
contextStringOuiCe que seul le modèle apprend, jusqu'à 1 000 caractères et 3 072 octets, contrôlé selon les règles de contenu
max_durationIntegerfacultatifDurée maximale une fois décroché, en secondes, de 30 à 300 (jusqu'au maximum du bot). 180 par défaut
ring_timeoutIntegerfacultatifDurée de sonnerie en secondes, de 30 à 45. 40 par défaut

Renvoie : {"voice_call_id": "…"} — cela veut seulement dire que la demande est prise en compte ; si cela a sonné et si la personne a répondu arrive dans des mises à jour voice_call. Refus : 403 VOICE_OUTBOUND_OFF: <raison>, 403 USER_UNAVAILABLE (toujours le même corps), 429, 503 VOICE_UNAVAILABLE. Impossible à appeler depuis une réponse de webhook.

answerVoiceCallToolQuery

POST/bot<jeton>/answerVoiceCallToolQuery

ParamètreTypeObligatoireDescription
tool_query_idStringOuiL'id de la VoiceCallToolQuery
resultString · Object · ArrayL'un des deuxRésultat de l'outil, jusqu'à 16 384 octets
errorStringL'un des deuxMessage d'échec du bot, jusqu'à 512 octets

Renvoie : True. La première réponse est la dernière. Trop tard : 400 TOOL_QUERY_EXPIRED: answered|timeout|cancelled|call_ended|unreachable ; identifiant inconnu : TOOL_QUERY_ID_INVALID ; réponse refusée : TOOL_RESULT_EMPTY·TOOL_RESULT_INVALID·TOOL_RESULT_TOO_LONG·TOOL_ERROR_TOO_LONG·TOOL_RESULT_REFUSED: <code>. À un POST de requête d'outil reçu par webhook, on peut aussi répondre dans le corps de la réponse.

setVoiceCallApiKey · deleteVoiceCallApiKey

POST/bot<jeton>/setVoiceCallApiKey

ParamètreTypeObligatoireDescription
providerStringOuigoogle (clé JSON de compte de service Vertex AI) ou openai (sk-…)
api_keyStringOuiLa clé. Uniquement dans le corps de la requête (dans la chaîne de requête : 400), jusqu'à 8 Kio

Renvoie : True — la clé n'est conservée qu'après avoir passé une session de test de la passerelle. API_KEY_INVALID, API_KEY_NO_REALTIME_ACCESS, 503 API_KEY_CHECK_UNAVAILABLE (clé non conservée), 403 VOICE_OWN_KEY_NOT_AVAILABLE (ce serveur n'accepte pas de clé propre). deleteVoiceCallApiKey ne prend aucun paramètre et renvoie toujours True. Aucune des deux méthodes ne peut être appelée par bots.sendCustomRequest, et setVoiceCallApiKey ne peut pas non plus l'être dans une réponse de webhook. Détails dans Votre propre clé de modèle.

Méthodes des serveurs MCP

MéthodeParamètresRenvoie
setVoiceCallMcpServerlabel, url, auth (objet), et en option audience, allowed_tools, requested_level, timeout_ms, tools (classification fournie par le propriétaire), declaration, auto_repinRésultat de l'enregistrement (status, job_id). Si le destinataire change : 400 MCP_CHANGE_NEEDS_CONFIRMATION, puis confirmation dans @BotFather
refreshVoiceCallMcpServerlabelNouvelle vérification (refreshing: true, job_id)
deleteVoiceCallMcpServerlabelTrue — fonctionne même si MCP est désactivé
getVoiceCallMcpBindingAucuniss, sub (bot:<id>), issuer_document, jwks_uri, audiences
createVoiceCallMcpClientKeylabelLa jwk publique et son thumbprint (la clé privée ne sort jamais de Pabal)

auth et les secrets s'envoient uniquement dans le corps de la requête. Sur un serveur sans MCP : 403 VOICE_NOT_AVAILABLE: MCP tools are not available on this server. Détails dans Bots vocaux — Serveurs MCP.

Recevoir les mises à jour vocales

voice_call, voice_call_tool_query et voice_call_transcript n'arrivent que si vous les demandez par leur nom — indiquez-les dans le allowed_updates de getUpdates ou de setWebhook. Elles n'arrivent pas avec une liste vide, et ce qui s'est produit avant votre demande n'est pas mis de côté. Une requête d'outil arrive par un POST séparé s'il y a un webhook, ou en tête du prochain getUpdates si getUpdates a été appelé dans les 15 dernières secondes.

VoiceCall

ChampTypeDescription
idStringIdentifiant de l'appel (entier décimal non signé)
directionStringincoming (un appel au bot) ou outgoing (un appel passé par le bot). Toujours présent
eventStringstarted, ended, missed, refused ; pour un appel passé par le bot, started, ended, not_answered, failed
from facultatifUserAppels au bot seulement — l'appelant : id, is_bot, first_name, last_name, language_code. Ni nom d'utilisateur ni numéro de téléphone
to facultatifObjectAppels passés par le bot seulement — {"id": …}, l'identifiant de la personne appelée et rien d'autre
purpose facultatifStringAppels passés par le bot seulement — le but de la demande
dateIntegerMoment de l'événement (secondes Unix). Pour started : à la fin de l'échange de clés pour un appel depuis une application, et quand l'audio de la montre est connecté pour un appel depuis l'Apple Watch. ended arrive jusqu'à 10 secondes plus tard sur un serveur qui attend la transcription ou où « Garder la conversation » est activé. Pour un appel passé par le bot, le ended d'un appel décroché arrive toujours jusqu'à 10 secondes plus tard, quels que soient les réglages du serveur, le temps de recevoir l'usage de la passerelle
max_duration facultatifIntegerDurée maximale de cet appel (secondes) — started, ended
start_date, duration facultatifIntegerHeure d'établissement de l'appel et durée en secondes de l'appel établi (horloge du serveur) — ended
end_reason facultatifStringcaller (callee pour un appel passé par le bot), bot, max_length, failed, operator, suspended — ended, missed
refused_reason facultatifStringbusy, budget, unavailable — refused
transcript facultatifObject{"turns": [{"role", "text", "offset_ms"}], "truncated"} — ended, quand la transcription était activée. Jamais pour un appel passé par le bot

VoiceCall n'a aucun champ indiquant si l'appelant a choisi « Garder la conversation ». C'est voulu — ce texte appartient à l'appelant et ne va pas au bot. C'est pourquoi, sur un serveur où « Garder la conversation » est activé, le ended de tous les appels hors mode flux attend le même temps, et le numéro du message qui suit le message d'appel est, pour tous les appels, supérieur d'au moins 31 à celui du message d'appel (les numéros sont réservés à l'avance).

VoiceCallToolQuery

ChampTypeDescription
idStringIdentifiant à passer à answerVoiceCallToolQuery
voice_call_idStringIdentifiant de l'appel
fromUserL'appelant (mêmes champs que dans VoiceCall)
nameStringNom de l'outil
argumentsStringArguments : le texte d'un objet JSON (vérifié par le serveur)
budget_msIntegerMillisecondes entre la réception et le moment où la réponse doit atteindre le serveur

VoiceCallTranscript

ChampTypeDescription
voice_call_idStringIdentifiant de l'appel
seqIntegerNuméro du tour de parole
roleStringcaller ou bot
textStringTexte écrit par l'IA. S'il contient un numéro de carte ou d'identification national, les chiffres deviennent des *
is_finalBooleanToujours true
offset_ms, dateIntegerMillisecondes depuis le début de l'audio de l'appel, et heure

N'arrive que par la Bot API HTTP. La transcription complète de l'appel se trouve dans le champ transcript du voice_call de fin.

Mode flux (mode=stream)

En mode flux, l'audio de l'appel va au serveur du propriétaire du bot au lieu du modèle d'IA de Pabal. Si vous envoyez à setVoiceCallSettings mode=stream, stream_url=wss://… et stream_secret=… (de 32 à 128 caractères ASCII imprimables, uniquement dans le corps de la requête), la passerelle de Pabal essaie une fois de se connecter à cette adresse (la sonde) et, si elle y parvient, le mode s'active. Il faut les conditions du propriétaire de bot et une version de l'application qui contient l'écran de confirmation du mode flux. Réglage, résultats de la sonde et exemples : Bots vocaux — Mode flux.

  • Connexion : TLS 1.2 ou plus, certificat public correspondant au nom de l'URL, sous-protocole pabal.voice.v1, pas de compression, 64 Kio par message et 4 Kio par texte au plus, pas de redirection.
  • Signature : 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 est l'hôte de l'URL que vous avez donnée. Vérifiez les 300 secondes, le nonce à usage unique, la comparaison octet par octet, et que start.call_id est égal à call (détails).
  • Audio : les messages texte sont des événements JSON, les binaires du PCM16 little-endian, mono, 24 kHz. La voix de l'appelant arrive par blocs de 20 ms (960 octets).
  • Pabal → bot : start (une fois) · live (l'annonce sur l'IA est finie) · audio · mark · cleared · buffer_full · stop (→ fermeture 1000).
  • Bot → Pabal : ready (dans les 3 secondes après start, en tout premier) · audio (après live) · clear · mark · hangup.

La forme de chaque message est donnée dans le tableau de Bots vocaux — Spécification.

Erreurs des méthodes vocales

Les codes d'erreur des méthodes vocales et leur signification sont regroupés dans Bots vocaux — Erreurs. Un 403 prend la forme Forbidden: <code>: <description> (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 est toujours exactement Forbidden: USER_UNAVAILABLE, sans description. Un dépassement de la limite horaire donne 429 avec retry_after.

Différences avec la Bot API de Telegram

  • Types de mises à jour : seuls message, edited_message, callback_query et les types propres aux bots vocaux de Pabal (voice_call, voice_call_tool_query, voice_call_transcript) arrivent. Pas de publications de canal, de requêtes inline, de paiements, de sondages, de changements de membres (my_chat_member), etc.
  • Mise en forme : parse_mode et entities sont ignorés et le texte est envoyé tel quel. Seuls les commandes, mentions, URL et hashtags sont mis en évidence automatiquement.
  • Types de conversation : 1:1 et groupes simples uniquement. Pas de canaux, de supergroupes ni de sujets de forum.
  • Médias : photos, fichiers (sendDocument), positions, positions en direct, lieux et contacts uniquement. Pas de messages vidéo ou vocaux qui se lisent dans l'application, pas de stickers, d'albums (sendMediaGroup) ni de sondages, et pas d'envoi par URL. Le téléversement et le téléchargement en HTTP sont limités à 20 Mo.
  • Positions : l'alerte de proximité d'une position en direct (proximity_alert_radius) est seulement enregistrée, jamais envoyée. Les déplacements de moins de 10 secondes ou de 10 m sont laissés de côté sans être pris en compte, et une fiche de contact envoyée par un bot ne porte pas de user_id.
  • Bots dans les groupes : il n'y a pas de mode confidentialité, le bot reçoit donc tous les messages du groupe.
  • File d'attente : les mises à jour non récupérées sont gardées en mémoire, jusqu'aux 1 000 plus récentes par bot, et perdues au redémarrage du serveur (Telegram les conserve 24 heures).
  • Webhooks : envoi d'une requête à la fois, dans l'ordre (max_connections est seulement conservé), pas de certificats auto-signés, aucune restriction de port.
  • ID : les ID d'utilisateur, de message et de fichier n'ont de sens que sur ce serveur. Comme il n'y a ni canaux ni supergroupes, il n'existe pas non plus d'ID de la forme -100….
  • Méthodes absentes : celles qui ne figurent pas dans la liste ci-dessus (forwardMessage, copyMessage, sendVideo, sendPoll, getChatMember, banChatMember, answerInlineQuery …) renvoient 404 Not Found: method not found.