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 :
GETetPOSTfonctionnent 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, etmultipart/form-datapour 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_code | Quand | Exemples de description |
|---|---|---|
400 | Paramètre incorrect | 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 | Jeton incorrect | Unauthorized |
403 | Pas le droit d'envoyer | Forbidden: bot can't initiate conversation with a user, Forbidden: bot is not a member of the group chat |
404 | Méthode ou fichier inexistant | Not Found: method not found |
409 | getUpdates alors qu'un webhook est configuré | Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first |
413 | Corps de plus de 12 Mo | Request Entity Too Large |
500 | Erreur interne du serveur | Internal 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
offset | Integer | Facultatif | Seulement 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é. |
limit | Integer | Facultatif | 1 à 100, 100 par défaut |
timeout | Integer | Facultatif | Secondes d'attente, de 0 à 50, 0 par défaut. Une valeur de 25 à 30 est recommandée. |
allowed_updates | Array of String | Facultatif | Types à 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
url | String | Oui | Adresse publique https://. Une chaîne vide supprime le webhook |
secret_token | String | Facultatif | 1 à 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_updates | Array of String | Facultatif | Parmi 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_updates | Boolean | Facultatif | Jette les mises à jour en attente |
max_connections | Integer | Facultatif | 1 à 100, 40 par défaut. Seulement conservé : la livraison se fait une requête à la fois par bot |
certificate | InputFile | Non pris en charge | 400 — utilisez un certificat public |
ip_address | String | Ignoré |
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ètre | Type | Obligatoire | Description |
|---|---|---|---|
drop_pending_updates | Boolean | Facultatif | Jette 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éthode | Ce qu'elle fait |
|---|---|
getMe | Informations sur le bot lui-même |
sendMessage | Envoyer un texte (boutons compris) |
sendPhoto | Envoyer une photo |
sendDocument | Envoyer un fichier |
sendLocation | Envoyer une position (y compris en direct) |
sendVenue | Envoyer un lieu (une position avec un nom et une adresse) |
sendContact | Envoyer une fiche de contact |
editMessageLiveLocation · stopMessageLiveLocation | Déplacer ou arrêter une position en direct |
editMessageText | Modifier le texte et les boutons d'un message envoyé |
editMessageCaption | Modifier la légende d'une photo |
editMessageReplyMarkup | Modifier seulement les boutons |
deleteMessage | Supprimer un message |
answerCallbackQuery | Répondre à un appui sur un bouton |
sendChatAction | Indicateur « en train d'écrire » (seulement accepté) |
getChat | Informations sur une conversation |
getFile | Chemin de téléchargement d'une photo reçue |
setMyCommands · getMyCommands · deleteMyCommands | Menu des commandes |
logOut · close | Pour compatibilité (ne font rien) |
getUpdates · setWebhook · deleteWebhook · getWebhookInfo | Recevoir les mises à jour (ci-dessus) |
setVoiceCallSettings · getVoiceCallSettings · endVoiceCall · sendVoiceCallContext · getVoiceCallUsage · startVoiceCall · answerVoiceCallToolQuery · setVoiceCallApiKey · setVoiceCallMcpServer … | Bots vocaux (voir Appels vocaux ci-dessous) |
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ètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation de destination (voir l'encadré ci-dessus) |
text | String | Oui | 1 à 4 096 caractères. Envoyé tel quel |
reply_markup | InlineKeyboardMarkup · ReplyKeyboardMarkup · ReplyKeyboardRemove · ForceReply | Facultatif | Boutons |
disable_notification | Boolean | Facultatif | Envoyer 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation de destination |
photo | InputFile ou String | Oui | Fichier 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 |
caption | String | Facultatif | 0 à 1 024 caractères |
reply_markup | Comme pour sendMessage | Facultatif | |
disable_notification | Boolean | Facultatif |
Renvoie : le Message envoyé (avec un nouveau file_id dans photo)
sendDocument
POST/bot<jeton>/sendDocument
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation de destination |
document | InputFile ou String | Oui | Fichier envoyé en multipart/form-data (tous formats, 20 Mo maximum), ou file_id d'un fichier reçu auparavant. Pas encore d'URL |
filename | String | Facultatif | Nom affiché chez le destinataire. À défaut, celui du fichier envoyé est utilisé |
caption | String | Facultatif | 0 à 1 024 caractères |
reply_markup | Comme pour sendMessage | Facultatif | |
disable_notification | Boolean | Facultatif | |
thumbnail, disable_content_type_detection | Ignoré | 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation de destination |
latitude, longitude | Float | Oui | Latitude (−90 à 90) et longitude (−180 à 180). Hors limites : 400 Bad Request: GEO_POINT_INVALID |
horizontal_accuracy | Float | Facultatif | Rayon d'incertitude en mètres, de 0 à 1 500. Arrondi à l'entier lors de l'enregistrement |
live_period | Integer | Facultatif | En 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 |
heading | Integer | Facultatif | Direction de déplacement d'une position en direct, 1 à 360 degrés |
proximity_alert_radius | Integer | Facultatif | Rayon 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_markup | Comme pour sendMessage | Facultatif | |
disable_notification | Boolean | Facultatif |
Renvoie : le Message envoyé (avec une Location dans location)
sendVenue
POST/bot<jeton>/sendVenue
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation de destination |
latitude, longitude | Float | Oui | Emplacement du lieu (comme pour sendLocation) |
title | String | Oui | Nom du lieu |
address | String | Oui | Adresse |
foursquare_id, foursquare_type | String | Facultatif | Identifiant et type du lieu chez Foursquare, transmis tels quels |
google_place_id, google_place_type | String | Facultatif | Identifiant et type du lieu chez Google. Utilisés seulement en l'absence de foursquare_id |
reply_markup | Comme pour sendMessage | Facultatif | |
disable_notification | Boolean | Facultatif |
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ètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation de destination |
phone_number | String | Oui | Numéro de téléphone, transmis tel qu'il est écrit |
first_name | String | Oui | Prénom |
last_name | String | Facultatif | Nom de famille |
vcard | String | Facultatif | Informations supplémentaires au format vCard, jusqu'à 64 Ko |
reply_markup | Comme pour sendMessage | Facultatif | |
disable_notification | Boolean | Facultatif |
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ètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation contenant le message |
message_id | Integer | Oui | Position en direct à déplacer (envoyée par le bot) |
latitude, longitude | Float | Oui | Nouvelle position |
horizontal_accuracy | Float | Facultatif | Rayon d'incertitude en mètres, de 0 à 1 500 |
heading | Integer | Facultatif | Direction de déplacement, 1 à 360 degrés |
proximity_alert_radius | Integer | Facultatif | Rayon de l'alerte de proximité en mètres. 0 la désactive |
live_period | Integer | Facultatif | Nouvelle 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_markup | InlineKeyboardMarkup | Facultatif | Nouveaux boutons |
inline_message_id | String | Non pris en charge | 400, 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
chat_id | Integer ou String | Oui | Conversation contenant le message |
message_id | Integer | Oui | Message à modifier (envoyé par le bot) |
text | String | Oui | Nouveau texte, 1 à 4 096 caractères |
reply_markup | InlineKeyboardMarkup | Facultatif | Nouveaux boutons. Sans ce paramètre, les boutons disparaissent (comme chez Telegram) |
inline_message_id | String | Non pris en charge | 400, 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
callback_query_id | String | Oui | Le callback_query.id de la mise à jour |
text | String | Facultatif | Texte affiché brièvement en haut de l'écran |
show_alert | Boolean | Facultatif | Si true, une fenêtre avec un bouton de confirmation |
url | String | Facultatif | Adresse que l'application doit ouvrir |
cache_time | Integer | Facultatif | Duré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ètre | Type | Obligatoire | Description |
|---|---|---|---|
commands | Array of BotCommand | Oui | 100 au maximum |
language_code | String | Facultatif | Enregistré comme liste propre à cette langue. L'application n'affiche pour l'instant que la liste par défaut, sans code de langue |
scope | BotCommandScope | Ignoré |
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.
| Champ | Type | Description |
|---|---|---|
update_id | Integer | Numéro qui augmente de 1. Sert d'offset pour getUpdates |
message facultatif | Message | Nouveau message adressé au bot (en 1:1, ou tous les messages d'un groupe dont le bot est membre) |
edited_message facultatif | Message | Message modifié |
callback_query facultatif | CallbackQuery | Appui sur un bouton inline |
voice_call facultatif | VoiceCall | Dé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 facultatif | VoiceCallToolQuery | Outil du bot appelé par le modèle pendant l'appel (n'arrive que si on le demande par son nom) |
voice_call_transcript facultatif | VoiceCallTranscript | Un tour de parole de la transcription pendant l'appel (n'arrive que si on le demande par son nom) |
User
| Champ | Type | Description |
|---|---|---|
id | Integer | ID d'utilisateur (n'a de sens que sur ce serveur) |
is_bot | Boolean | true pour un bot |
first_name | String | Prénom. Deleted Account pour un compte supprimé |
last_name facultatif | String | Nom de famille |
username facultatif | String | Nom d'utilisateur (sans @) |
Chat
| Champ | Type | Description |
|---|---|---|
id | Integer | Pour une personne, son ID (positif) ; pour un groupe simple, un nombre négatif |
type | String | private ou group |
title facultatif | String | Nom du groupe (group) |
first_name, last_name, username facultatif | String | Nom et nom d'utilisateur de l'interlocuteur (private) |
Message
| Champ | Type | Description |
|---|---|---|
message_id | Integer | Numéro du message dans cette conversation |
from facultatif | User | Expéditeur |
chat | Chat | Conversation contenant le message |
date | Integer | Heure d'envoi (secondes Unix) |
edit_date facultatif | Integer | Heure de la dernière modification |
text facultatif | String | Texte (toujours présent, sauf pour un message photo, fichier, position, lieu ou contact) |
entities facultatif | Array of MessageEntity | Commandes, mentions, URL et hashtags du texte |
photo facultatif | Array of PhotoSize | Photo (chez Pabal, l'original seul) |
document facultatif | Document | Fichier |
location facultatif | Location | Position ou position en direct. Un message de lieu porte aussi sa position ici |
venue facultatif | Venue | Lieu |
contact facultatif | Contact | Fiche de contact |
caption facultatif | String | Légende de la photo |
caption_entities facultatif | Array of MessageEntity | Commandes, mentions, URL et hashtags de la légende |
reply_markup facultatif | InlineKeyboardMarkup | Boutons inline attachés au message |
MessageEntity
| Champ | Type | Description |
|---|---|---|
type | String | bot_command, mention, url, hashtag |
offset | Integer | Position de début (en unités de code UTF-16) |
length | Integer | Longueur (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
| Champ | Type | Description |
|---|---|---|
file_id | String | ID utilisé pour télécharger (getFile) et pour renvoyer (sendPhoto) |
file_unique_id | String | Même valeur pour une même photo, même d'un bot à l'autre. Inutilisable pour télécharger |
width, height | Integer | Dimensions en pixels |
file_size | Integer | Octets |
Document
| Champ | Type | Description |
|---|---|---|
file_id | String | ID utilisé pour télécharger (getFile) et pour renvoyer (sendDocument) |
file_unique_id | String | Même valeur pour un même fichier, même d'un bot à l'autre. Inutilisable pour télécharger |
file_name | String | Nom donné par l'expéditeur |
mime_type | String | Format annoncé par l'expéditeur |
file_size | Integer | Octets |
Location
| Champ | Type | Description |
|---|---|---|
latitude, longitude | Float | Latitude et longitude |
horizontal_accuracy facultatif | Float | Rayon d'incertitude en mètres |
live_period facultatif | Integer | Duré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 facultatif | Integer | Direction de déplacement, 1 à 360 degrés |
proximity_alert_radius facultatif | Integer | Rayon 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
| Champ | Type | Description |
|---|---|---|
location | Location | Emplacement du lieu |
title | String | Nom du lieu |
address | String | Adresse |
foursquare_id, foursquare_type facultatif | String | Identifiant et type du lieu chez Foursquare |
google_place_id, google_place_type facultatif | String | Identifiant et type du lieu chez Google |
Contact
| Champ | Type | Description |
|---|---|---|
phone_number | String | Le numéro, tel que l'expéditeur l'a écrit |
first_name | String | Prénom |
last_name facultatif | String | Nom de famille |
user_id facultatif | Integer | Le 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 facultatif | String | Informations supplémentaires au format vCard |
File
| Champ | Type | Description |
|---|---|---|
file_id, file_unique_id | String | Comme pour PhotoSize |
file_size | Integer | Octets |
file_path | String | De la forme photos/<file_id>.jpg ou documents/<file_id>. À ajouter après /file/bot<jeton>/ pour télécharger |
CallbackQuery
| Champ | Type | Description |
|---|---|---|
id | String | ID à passer à answerCallbackQuery |
from | User | Personne qui a appuyé sur le bouton |
message facultatif | Message | Message portant le bouton |
chat_instance | String | Valeur représentant cette conversation |
data facultatif | String | Le 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
| Champ | Type | Description |
|---|---|---|
text | String | Texte du bouton |
callback_data l'un des deux | String | Valeur envoyée au bot quand on appuie, 1 à 64 octets |
url l'un des deux | String | Adresse ouverte quand on appuie |
Les autres types, comme switch_inline_query, web_app, login_url ou pay, n'existent pas encore (400).
ReplyKeyboardMarkup
| Champ | Type | Description |
|---|---|---|
keyboard | Array of Array of KeyboardButton | Pavé de boutons sous le champ de saisie |
resize_keyboard, one_time_keyboard, is_persistent, selective facultatif | Boolean | Ajuster la taille · masquer après usage · toujours visible · seulement pour certaines personnes |
input_field_placeholder facultatif | String | Texte 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
| Champ | Type | Description |
|---|---|---|
command | String | 1 à 32 caractères : minuscules latines, chiffres, tiret bas (sans /) |
description | String | 1 à 256 caractères |
WebhookInfo
| Champ | Type | Description |
|---|---|---|
url | String | Adresse du webhook, chaîne vide s'il n'y en a pas |
has_custom_certificate | Boolean | Toujours false |
pending_update_count | Integer | Nombre de mises à jour en attente de livraison |
ip_address facultatif | String | Dernière IP vers laquelle un envoi a eu lieu |
last_error_date facultatif | Integer | Heure du dernier échec (secondes Unix) |
last_error_message facultatif | String | Raison du dernier échec (liste) |
max_connections facultatif | Integer | Valeur passée à setWebhook |
allowed_updates facultatif | Array of String | Valeur 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
enabled | Boolean | Facultatif | Activer 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 |
instructions | String | Facultatif | Instructions du modèle, jusqu'à 8 192 octets. "" les efface (impossible pour un bot géré activé) |
greeting | String | Facultatif | Message d'accueil, jusqu'à 512 octets. Avec "", le modèle s'en charge |
voice | String | Facultatif | Identifiant de voix, kore par défaut (liste) |
language | String | Facultatif | ko-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_duration | Integer | Facultatif | Secondes, de 60 à limits.max_call_duration |
max_concurrent_calls | Integer | Facultatif | De 1 à limits.max_concurrent_calls |
tools | Array of VoiceCallTool | Facultatif | Outils 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 |
transcript | Boolean | Facultatif | Interrupteur de la transcription. L'activer exige les conditions du propriétaire de bot |
mode | String | Facultatif | managed (le modèle d'IA de Pabal) ou stream (mode flux) |
stream_url, stream_secret | String | Facultatif | Avec 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
voice_call_id | String | Oui | voice_call.id |
farewell | Boolean | Facultatif | true 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
voice_call_id | String | Oui | Un appel établi |
text | String | Oui | Note du propriétaire du bot pour le modèle. Jusqu'à 2 000 caractères et 6 144 octets, soumise aux règles de contenu |
respond | Boolean | Facultatif | false 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
period | String | Facultatif | today (par défaut) ou month |
month | String | Facultatif | YYYY-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ètre | Type | Obligatoire | Description |
|---|---|---|---|
user_id | Integer | Oui | La personne à appeler |
purpose | String | Oui | Celui que le bot a choisi parmi reminder, wake_up, delivery, appointment |
context | String | Oui | Ce que seul le modèle apprend, jusqu'à 1 000 caractères et 3 072 octets, contrôlé selon les règles de contenu |
max_duration | Integer | facultatif | Durée maximale une fois décroché, en secondes, de 30 à 300 (jusqu'au maximum du bot). 180 par défaut |
ring_timeout | Integer | facultatif | Duré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ètre | Type | Obligatoire | Description |
|---|---|---|---|
tool_query_id | String | Oui | L'id de la VoiceCallToolQuery |
result | String · Object · Array | L'un des deux | Résultat de l'outil, jusqu'à 16 384 octets |
error | String | L'un des deux | Message 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ètre | Type | Obligatoire | Description |
|---|---|---|---|
provider | String | Oui | google (clé JSON de compte de service Vertex AI) ou openai (sk-…) |
api_key | String | Oui | La 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éthode | Paramètres | Renvoie |
|---|---|---|
setVoiceCallMcpServer | label, url, auth (objet), et en option audience, allowed_tools, requested_level, timeout_ms, tools (classification fournie par le propriétaire), declaration, auto_repin | Résultat de l'enregistrement (status, job_id). Si le destinataire change : 400 MCP_CHANGE_NEEDS_CONFIRMATION, puis confirmation dans @BotFather |
refreshVoiceCallMcpServer | label | Nouvelle vérification (refreshing: true, job_id) |
deleteVoiceCallMcpServer | label | True — fonctionne même si MCP est désactivé |
getVoiceCallMcpBinding | Aucun | iss, sub (bot:<id>), issuer_document, jwks_uri, audiences |
createVoiceCallMcpClientKey | label | La 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
| Champ | Type | Description |
|---|---|---|
id | String | Identifiant de l'appel (entier décimal non signé) |
direction | String | incoming (un appel au bot) ou outgoing (un appel passé par le bot). Toujours présent |
event | String | started, ended, missed, refused ; pour un appel passé par le bot, started, ended, not_answered, failed |
from facultatif | User | Appels 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 facultatif | Object | Appels passés par le bot seulement — {"id": …}, l'identifiant de la personne appelée et rien d'autre |
purpose facultatif | String | Appels passés par le bot seulement — le but de la demande |
date | Integer | Moment 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 facultatif | Integer | Durée maximale de cet appel (secondes) — started, ended |
start_date, duration facultatif | Integer | Heure d'établissement de l'appel et durée en secondes de l'appel établi (horloge du serveur) — ended |
end_reason facultatif | String | caller (callee pour un appel passé par le bot), bot, max_length, failed, operator, suspended — ended, missed |
refused_reason facultatif | String | busy, budget, unavailable — refused |
transcript facultatif | Object | {"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
| Champ | Type | Description |
|---|---|---|
id | String | Identifiant à passer à answerVoiceCallToolQuery |
voice_call_id | String | Identifiant de l'appel |
from | User | L'appelant (mêmes champs que dans VoiceCall) |
name | String | Nom de l'outil |
arguments | String | Arguments : le texte d'un objet JSON (vérifié par le serveur) |
budget_ms | Integer | Millisecondes entre la réception et le moment où la réponse doit atteindre le serveur |
VoiceCallTranscript
| Champ | Type | Description |
|---|---|---|
voice_call_id | String | Identifiant de l'appel |
seq | Integer | Numéro du tour de parole |
role | String | caller ou bot |
text | String | Texte écrit par l'IA. S'il contient un numéro de carte ou d'identification national, les chiffres deviennent des * |
is_final | Boolean | Toujours true |
offset_ms, date | Integer | Millisecondes 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>").hostest 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 questart.call_idest é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èsstart, en tout premier) · audio (aprèslive) ·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_queryet 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_modeetentitiessont 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 deuser_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_connectionsest 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…) renvoient404 Not Found: method not found.