Telegram bot commands: BotFather, setMyCommands and webhook
The commands users see after typing / in a chat with the bot are set in @BotFather. Send it /setcommands, pick the bot and send the list, one command per line, without the slash:
start - Start the bot
help - What the bot can do
settings - Settings
Rules from the Bot API:
- a command is 1–32 characters: lowercase English letters, digits and underscores;
- a description is 1–256 characters;
- a list holds up to 100 commands.
Telegram asks every bot to support /start, /help and, if the bot has settings, /settings. The first time a user opens a chat with the bot, they see a Start button.
The menu is only a hint. A message can contain any command, including ones you didn't list, and the bot isn't told which list the user saw. Check commands and permissions on your server. In a group with several bots, add the bot's username to the command, /help@my_bot, so it reaches the right one.
Set commands with the API: setMyCommands
TOKEN="123456789:AA..."
curl -s "https://api.telegram.org/bot$TOKEN/setMyCommands" \
-H 'Content-Type: application/json' \
-d '{"commands": [
{"command": "start", "description": "Start the bot"},
{"command": "help", "description": "What the bot can do"}
]}'
The response is {"ok":true,"result":true}. getMyCommands returns the current list, deleteMyCommands deletes it.
language_code and scope give different users different lists:
# The menu for users whose Telegram is in Russian
curl -s "https://api.telegram.org/bot$TOKEN/setMyCommands" \
-H 'Content-Type: application/json' \
-d '{"language_code": "ru", "commands": [
{"command": "start", "description": "Запустить бота"},
{"command": "help", "description": "Что умеет бот"}
]}'
# The menu for administrators of every group: repeat start and help
curl -s "https://api.telegram.org/bot$TOKEN/setMyCommands" \
-H 'Content-Type: application/json' \
-d '{"scope": {"type": "all_chat_administrators"}, "commands": [
{"command": "start", "description": "Start the bot"},
{"command": "help", "description": "What the bot can do"},
{"command": "ban", "description": "Ban a user"}
]}'
Scope types: default, all_private_chats, all_group_chats, all_chat_administrators, chat, chat_administrators, chat_member. Each user sees one list, not a merge: a list for a scope or a language replaces the whole menu. Telegram picks the list for the narrowest scope that has one, first in the user's language, then without a language, and falls back to default. Pass the same scope and language_code to getMyCommands and deleteMyCommands.
BotFather commands
| Command | What it does |
|---|---|
/newbot |
create a bot and get its token |
/mybots |
your bots, with buttons to edit each one |
/setname |
change the bot's name |
/setdescription |
the "What can this bot do?" text, up to 512 characters |
/setabouttext |
the text on the bot's profile, up to 120 characters |
/setuserpic |
the profile picture |
/setcommands |
the command menu |
/setjoingroups |
allow or forbid adding the bot to groups |
/setprivacy |
privacy mode: which group messages the bot receives |
/setinline |
inline mode |
/token |
a new token, if the old one leaked |
/deletebot |
delete the bot; there's no undo |
BotFather adds commands over time. Type / in the chat with it to see the current list.
Bot API URLs: token and webhook
Every method lives at https://api.telegram.org/bot<token>/METHOD, over GET or POST:
# Check the token: returns the bot's id, name and username
curl -s "https://api.telegram.org/bot$TOKEN/getMe"
# Set a webhook: Telegram sends updates to this HTTPS URL
curl -s "https://api.telegram.org/bot$TOKEN/setWebhook" \
-d url=https://example.com/telegram/webhook \
-d secret_token=my-secret-123
# Webhook status: url, pending_update_count, last_error_message
curl -s "https://api.telegram.org/bot$TOKEN/getWebhookInfo"
# Remove the webhook and drop the queued updates
curl -s "https://api.telegram.org/bot$TOKEN/deleteWebhook" \
-d drop_pending_updates=true
- A webhook works on ports 443, 80, 88 and 8443, always over HTTPS, port 80 included.
- With
secret_token, every request from Telegram carries the headerX-Telegram-Bot-Api-Secret-Tokenwith that value. Compare it to drop requests that didn't come from Telegram. - If your server answers with anything other than 2XX, Telegram retries the update and gives up after several attempts.
getUpdatesdoesn't work while a webhook is set:Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first. To switch to polling, calldeleteWebhook.
The token in the URL ends up in shell history and server logs. If it leaks, get a new one with /token in BotFather.