Advanced

Stories

Stories are 24-hour ephemeral posts that show up on a user's profile and in friends' story feeds. Same API surface as messages, different lifetime and visibility model.

What stories are

Stories live on a peer's profile rather than in a chat. They expire after a chosen period (default 24 hours), can be pinned to the profile so they stay visible, and have their own privacy controls separate from regular chat privacy.

Posting a story

storyID, err := client.SendStory("me", "./vacation.jpg", &telegram.StoryOptions{
	Caption: "lake day",
	Pinned:  true,
	Period:  24 * time.Hour,
	Privacy: telegram.StoryContacts,
})
if err != nil { log.Fatal(err) }
fmt.Println("posted:", storyID)
storyID, err := client.SendStory("me", "./vacation.jpg", &telegram.StoryOptions{
	Caption: "lake day",
	Pinned:  true,
	Period:  24 * time.Hour,
	Privacy: telegram.StoryContacts,
})
if err != nil { log.Fatal(err) }
fmt.Println("posted:", storyID)

Notable options:

Caption / ParseMode
Caption text and how to parse formatting.
Period time.Duration
Lifetime. Telegram caps at 7 days for premium accounts, 24 hours for free.
Pinned bool
Show on the profile after expiry.
Noforwards bool
Prevent recipients from sharing the story.
Privacy StoryPrivacy
One of StoryPublic, StoryContacts, StoryCloseFriends, StorySelected. For fine-grained allow/deny lists use PrivacyRules and AllowedUsers.
Music InputDocument
Attach a music document; renders as an audio overlay on the story.

Reading stories

active, err := client.GetStories("@somechannel")
for _, s := range active {
	if obj, ok := s.(*telegram.StoryItemObj); ok {
		fmt.Println(obj.ID, obj.Caption)
	}
}

// pinned strip on the profile:
pinned, err := client.GetPinnedStories("@somechannel", 0, 100)

// expired archive (author view only):
archive, err := client.GetStoriesArchive("me", 0, 100)
active, err := client.GetStories("@somechannel")
for _, s := range active {
	if obj, ok := s.(*telegram.StoryItemObj); ok {
		fmt.Println(obj.ID, obj.Caption)
	}
}

// pinned strip on the profile:
pinned, err := client.GetPinnedStories("@somechannel", 0, 100)

// expired archive (author view only):
archive, err := client.GetStoriesArchive("me", 0, 100)

GetStories returns active (unexpired) stories for a peer. GetPeerStories returns the full envelope (state + stories). Pinned and archived stories are separate lists via GetPinnedStories and GetStoriesArchive.

// mark stories as seen (up to maxID):
client.MarkStoriesRead("@durov", maxStoryID)
// mark stories as seen (up to maxID):
client.MarkStoriesRead("@durov", maxStoryID)

Viewers and reactions

// emoji reaction:
client.ReactToStory("@durov", storyID, "๐Ÿ”ฅ")

// remove a reaction:
client.ReactToStory("@durov", storyID, "")

// custom emoji:
client.ReactToStory("@durov", storyID, int64(customEmojiDocumentID))
// emoji reaction:
client.ReactToStory("@durov", storyID, "๐Ÿ”ฅ")

// remove a reaction:
client.ReactToStory("@durov", storyID, "")

// custom emoji:
client.ReactToStory("@durov", storyID, int64(customEmojiDocumentID))

ReactToStory attaches a reaction. Pass a string for an emoji reaction, an int64 document id for a custom-emoji reaction, or an empty string to remove it. From the author side, the raw StoriesGetStoryViewsList returns the list of viewers + their reactions.

Channel stories

Channels can also post stories (with boost-gated quotas). The same API works; pass the channel as the peer. Story methods on a channel require admin rights with the EditStories flag.