Callback queries
A callback query is what arrives at your bot when a user taps an inline-keyboard button with a Data payload. You answer it within 15 seconds; if you do not, the spinner on the button stays forever.
The flow
- Bot sends a message with inline-keyboard buttons that carry data payloads.
- User taps a button.
- Telegram delivers a
CallbackQueryto the bot with the data. - Bot calls
Answer— either a silent ack or a popup / alert. - Optionally the bot edits the original message to reflect the new state.
Registering a handler
The callback handler signature is func(*CallbackQuery) error. Wire it through On or directly:
client.On("callback:vote:*", onVote)
client.AddCallbackHandler("vote:*", onVote)client.On("callback:vote:*", onVote)
client.AddCallbackHandler("vote:*", onVote)Data buttons
kbd := telegram.NewKeyboard().AddRow(
telegram.Button.Data("Vote ↑", "vote:up"),
telegram.Button.Data("Vote ↓", "vote:dn"),
).Build()
client.SendMessage(peerID, "Was it useful?", &telegram.SendOptions{
ReplyMarkup: kbd,
})
client.On("callback:vote:*", func(q *telegram.CallbackQuery) error {
switch string(q.Data) {
case "vote:up":
_, err := q.Answer("Thanks!")
return err
case "vote:dn":
_, err := q.Answer("Noted.")
return err
}
return nil
})kbd := telegram.NewKeyboard().AddRow(
telegram.Button.Data("Vote ↑", "vote:up"),
telegram.Button.Data("Vote ↓", "vote:dn"),
).Build()
client.SendMessage(peerID, "Was it useful?", &telegram.SendOptions{
ReplyMarkup: kbd,
})
client.On("callback:vote:*", func(q *telegram.CallbackQuery) error {
switch string(q.Data) {
case "vote:up":
_, err := q.Answer("Thanks!")
return err
case "vote:dn":
_, err := q.Answer("Noted.")
return err
}
return nil
})Data payloads are arbitrary bytes up to 64 bytes long. Convention is a colon-separated verb and arguments (vote:up, delete:42, page:next:5). On the receiving side, q.Data is a []byte — cast with string(q.Data) when you want to switch on it.
Answering the query
The signature is q.Answer(text, ...opts). Empty text is a silent ack:
_, _ = q.Answer("")_, _ = q.Answer("")Non-empty text shows as a toast (top of screen, a few seconds):
_, _ = q.Answer("Thanks!")_, _ = q.Answer("Thanks!")Modal alert (sticks until dismissed):
_, err := q.Answer("That permission has been revoked.",
&telegram.CallbackOptions{Alert: true})_, err := q.Answer("That permission has been revoked.",
&telegram.CallbackOptions{Alert: true})CallbackOptions fields:
- Alert
bool - Show as a modal alert instead of a top-of-screen toast.
- CacheTime
int32 - Seconds the client should cache this answer for. Subsequent taps inside the cache window show the same answer without round-tripping to the bot.
- URL
string - For game bots: the URL to open instead of (or in addition to) the answer text.
Edit and respond
Most callback handlers also update the message in place:
_, err := q.Edit("voted!", &telegram.SendOptions{
ReplyMarkup: telegram.NewKeyboard().AddRow(
telegram.Button.Data("Undo", "vote:undo"),
).Build(),
})_, err := q.Edit("voted!", &telegram.SendOptions{
ReplyMarkup: telegram.NewKeyboard().AddRow(
telegram.Button.Data("Undo", "vote:undo"),
).Build(),
})q.Edit edits the message the button was attached to, taking the same SendOptions you would pass to EditMessage. q.Respond sends a new message in the same chat:
_, err := q.Respond("Here is more detail:", &telegram.SendOptions{
ReplyID: q.MessageID,
})_, err := q.Respond("Here is more detail:", &telegram.SendOptions{
ReplyID: q.MessageID,
})Other helpers on *CallbackQuery: GetMessage(), GetSender(), GetChat(), GetChannel(), RespondMedia(media, opts), Conv(timeout) to start a conversation in the chat the button lived on.
URL, login, pay buttons
Buttons that open a URL (Button.URL), request login (Button.Auth), or trigger payment (Button.Buy) do not produce callback queries — the client handles them directly. WebView buttons (Button.WebView) similarly do not show up here; the bot receives a service message containing the data the Web App submitted, handled via the action event on the dispatcher.
