inline mode
let users type @your_bot query in any chat and pick a result generated by your bot.
answer inline queries
inline query handlers must answer with a list of results. keep the response fast, cache where
possible, and use is_personal when results depend on the current user.
bot.on("inline_query", async (ctx) => {
const query = ctx.update.inline_query!;
const results = await search(query.query);
await ctx.api.call("answerInlineQuery", {
inline_query_id: query.id,
cache_time: 10,
is_personal: true,
results: results.map((item) => ({
type: "article",
id: item.id,
title: item.title,
input_message_content: { message_text: item.text },
})),
});
});track chosen results
if enabled in botfather, telegram sends chosen_inline_result after a user picks one of
your results. use it for analytics, not for critical business logic.
bot.on("chosen_inline_result", async (ctx) => {
const chosen = ctx.update.chosen_inline_result!;
await analytics.track("inline_chosen", {
resultId: chosen.result_id,
userId: chosen.from.id,
query: chosen.query,
});
});switch inline buttons
inline keyboard buttons can open the inline picker with a prefilled query. this is useful for sharing products, documents, search results, or mini app content.
new InlineKeyboard()
.switchInline("share", "product:42")
.row()
.switchInlineCurrentChat("search here", "cats");rules of thumb
- return stable result ids so analytics and caches stay meaningful.
- keep result payloads small; the user is waiting inside telegram's inline picker.
- use
cache_timeaggressively for public search results. - set
is_personalfor private/user-specific results. - add
inline_queryandchosen_inline_resulttoallowedUpdateswhen polling.