Advanced

Inline & reply keyboards

Two button systems live side by side. Inline keyboards attach to a specific message and survive edits. Reply keyboards replace the user's regular keyboard with a panel of quick replies.

Two kinds of keyboards

Inline keyboards are buttons under a message. They produce callback queries, open URLs, launch Web Apps, request logins, or trigger payment flows. They persist with the message; editing the message can change the buttons.

Reply keyboards replace the user's on-screen text keyboard with a panel of buttons. They do not produce callback queries — tapping a button sends its label as a regular text message. Once shown, they stay until you replace or remove them.

Inline keyboards

kbd := telegram.NewKeyboard().
	Row(
		telegram.Button.Data("Yes", "y"),
		telegram.Button.Data("No",  "n"),
	).
	Row(
		telegram.Button.URL("Read more", "https://gogram.dev"),
	).
	Build()

client.SendMessage(peerID, "Continue?", &telegram.SendOptions{
	ReplyMarkup: kbd,
})
kbd := telegram.NewKeyboard().
	Row(
		telegram.Button.Data("Yes", "y"),
		telegram.Button.Data("No",  "n"),
	).
	Row(
		telegram.Button.URL("Read more", "https://gogram.dev"),
	).
	Build()

client.SendMessage(peerID, "Continue?", &telegram.SendOptions{
	ReplyMarkup: kbd,
})

Build with NewKeyboard and chain .Row(...) for each row. .Build() returns a ReplyMarkup ready to pass on SendOptions.

Button types

Data(text, data)
Standard callback button. Data ≤ 64 bytes.
URL(text, url)
Open the URL on tap.
WebApp(text, url)
Open the URL inside a Mini App with the Telegram JS bridge.
Login(text, url, opts)
OAuth-style flow that passes a verified Telegram identity to your server.
Switch(text, query, sameChat)
Open inline mode in the current or another chat with a pre-filled query.
Game(text)
Open a Telegram HTML5 Game.
Buy(text)
Trigger the payment flow for a previously-sent invoice.
CopyText(text, copy)
Copy a string to the clipboard.

Reply keyboards

kbd := telegram.NewKeyboard().
	Row(
		telegram.Button.Reply("📊 Stats"),
		telegram.Button.Reply("🛠 Settings"),
	).
	WithOneTime(true).
	WithResize(true).
	BuildReply()

client.SendMessage(peerID, "Pick one:", &telegram.SendOptions{ReplyMarkup: kbd})
kbd := telegram.NewKeyboard().
	Row(
		telegram.Button.Reply("📊 Stats"),
		telegram.Button.Reply("🛠 Settings"),
	).
	WithOneTime(true).
	WithResize(true).
	BuildReply()

client.SendMessage(peerID, "Pick one:", &telegram.SendOptions{ReplyMarkup: kbd})

Options on the builder: .WithOneTime(true) hides the keyboard after one use, .WithResize(true) shrinks the buttons to fit content, .WithPlaceholder("type here") sets the input placeholder.

Buttons can also request data from the user: a contact card (Button.RequestContact), a location (Button.RequestLocation), a poll (Button.RequestPoll), or a peer (Button.RequestPeer).

ForceReply

Force the user's next message in the chat to start as a reply to this one. Helps guide conversational flows without an explicit Ask wait:

client.SendMessage(peerID, "What is your name?", &telegram.SendOptions{
	ReplyMarkup: telegram.NewForceReply(true),
})
client.SendMessage(peerID, "What is your name?", &telegram.SendOptions{
	ReplyMarkup: telegram.NewForceReply(true),
})

Removing a keyboard

client.SendMessage(peerID, "ok", &telegram.SendOptions{
	ReplyMarkup: telegram.NewRemoveKeyboard(),
})
client.SendMessage(peerID, "ok", &telegram.SendOptions{
	ReplyMarkup: telegram.NewRemoveKeyboard(),
})

Removes the active reply keyboard. Inline keyboards are removed by editing the message with an empty ReplyMarkup.