Sending messages
The single most-used method in the library. SendMessage takes a destination, a body, and an optional bag of switches that controls everything from parse mode to flood-priority.
The basics
_, err := client.SendMessage("me", "hello, saved messages")_, err := client.SendMessage("me", "hello, saved messages")That call goes to your own "Saved Messages" chat — useful for development. To message someone else by username:
_, err := client.SendMessage("@durov", "ping")_, err := client.SendMessage("@durov", "ping")The return value is a *NewMessage: the sent message wrapped in gogram's update helper, the same type you get inside an incoming handler. You can chain operations on it — .Edit(...), .Delete(), .React(...), .Pin()— without re-fetching.
Peer ids
The peerID any parameter accepts any of:
- An
int64chat or user id (123456,-1001234for channels). - A username string (
"@durov"or"durov", the @ is optional). - The literal string
"me"for Saved Messages. - A phone number (
"+15551234567") when you have the contact saved. - A t.me link (
"https://t.me/durov"). - An already-resolved
InputPeerif you have one.
gogram resolves what you pass and caches the resulting InputPeer. After the first send to a username, subsequent sends are free of the contacts.resolveUsername round-trip.
SendOptions
The third argument is a pointer to SendOptions. Common fields:
- ParseMode
string "Markdown"or"HTML". Defaults to whatever you set on the client.- ReplyID
int32 - Message id of what this reply targets.
- TopicID
int32 - Forum topic id, for forum-enabled supergroups.
- Silent
bool - Deliver without notification sound.
- NoForwards
bool - Disable forwarding and saving on the recipient side.
- LinkPreview
bool - Generate a preview for URLs in the body. Default is whatever Telegram's server picks.
- InvertMedia
bool - Show media below the caption instead of above.
- ReplyMarkup
ReplyMarkup - Inline or reply keyboard. See Inline keyboards.
- SendAs
any - Post as a channel or linked group; takes any peer id form.
- ScheduleDate
int32 - Unix timestamp; the message stays in the schedule queue until then.
- NoForwards / Silent / Spoiler / TTL / Effect
- Various flags that map directly onto fields of the underlying TL
messages.sendMessage.
client.SendMessage(peerID, "*important*", &telegram.SendOptions{
ParseMode: "Markdown",
ReplyID: 42,
Silent: true,
NoForwards: true,
LinkPreview: false,
})client.SendMessage(peerID, "*important*", &telegram.SendOptions{
ParseMode: "Markdown",
ReplyID: 42,
Silent: true,
NoForwards: true,
LinkPreview: false,
})Replies and threads
client.On("message:*", func(m *telegram.NewMessage) error {
_, err := m.Reply("got it")
return err
})client.On("message:*", func(m *telegram.NewMessage) error {
_, err := m.Reply("got it")
return err
})NewMessage.Reply sets ReplyID automatically. To reply across threads in a supergroup or to a discussion-linked channel post, also set TopicID. For forum supergroups, every topic has an id you get from incoming messages or from channels.getForumTopics.
Silent and protected sends
Silent: truesends without notification sound — good for chatty bots posting status updates at 3am. NoForwards: true sets the protected flag on the message; the recipient cannot forward or save it. Both flags are independent and stack with everything else.
Scheduling
Telegram natively schedules messages on the server. The client submits the message, the server queues it for the requested time, the recipient sees it at that exact moment even if your bot is offline.
import "time" client.ScheduleMessage(peerID, "morning standup in 5", time.Now().Add(5*time.Minute))
import "time"
client.ScheduleMessage(peerID, "morning standup in 5", time.Now().Add(5*time.Minute))For repeating schedules, set ScheduleRepeatPeriod on SendOptions instead.
Sending as a channel
In a discussion group linked to a channel, users with the appropriate permission can post as the channel rather than as themselves. Bots in admin position can do the same:
client.SendMessage(peerID, "shipped", &telegram.SendOptions{
SendAs: "@my_channel",
})client.SendMessage(peerID, "shipped", &telegram.SendOptions{
SendAs: "@my_channel",
})Bots and group privacy
Streaming partial messages
For LLM-style typewriter effects, StreamMessage sends an initial message and then edits it repeatedly. Telegram debounces the edits server-side so you do not need to rate-limit yourself.
client.StreamMessage(peerID, func(update func(string)) {
update("Working")
update("Working.")
update("Working..")
update("Done")
})client.StreamMessage(peerID, func(update func(string)) {
update("Working")
update("Working.")
update("Working..")
update("Done")
})