Inline

Users can interact with your bot via inline queries, straight from the text input field in any chat.
This article describes the full inline bot flow, using the MTProto API.

For a simplified description using the HTTP bot API, see here ».

1. Making an inline query

messages.botResults#e021f2f6 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM switch_webview:flags.3?InlineBotWebView results:Vector<BotInlineResult> cache_time:int users:Vector<User> = messages.BotResults;

---functions---

messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;

When, in a graphical client, the user starts a message with an @, clients should:

  • Use the cached top peer rating for inline bots to show a list of frequently used inline bots.
  • If the user chooses a bot from the recent bot list or:
  • Finishes typing a full username followed by a whitespace, and if the username resolves to a valid bot
  • messages.getInlineBotResults is called, with the following parameters:
    • bot - The bot peer
    • peer - The chat where the user made the query (or inputPeerEmpty for GIF searches and other queries to built-in bots specified in the config)
    • geo_point - The user's current geolocation, if the bot requires location-based inline results (the bot_inline_geo flag of the bot's user constructor will be set)
    • query - What the user typed after the bot's username
    • offset - If the user scrolls past the first len(results) results, and next_offset field is set, the inline query should be repeated with this offset.

2. Answering to an inline query

inputBotInlineMessageMediaAuto#3380c786 flags:# invert_media:flags.3?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageText#3dcd7a87 flags:# no_webpage:flags.0?true invert_media:flags.3?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaGeo#96929a85 flags:# geo_point:InputGeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaContact#a6edbffd flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;

inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultDocument#fff8fdc4 flags:# id:string type:string title:flags.1?string description:flags.2?string document:InputDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:InputBotInlineMessage = InputBotInlineResult;

updateBotInlineQuery#496f379c flags:# query_id:long user_id:long query:string geo:flags.0?GeoPoint peer_type:flags.1?InlineQueryPeerType offset:string = Update;

---functions---

messages.setInlineBotResults#bb12a419 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM switch_webview:flags.4?InlineBotWebView = Bool;

Bots can answer to incoming updateBotInlineQuery updates using messages.setInlineBotResults.
Just like its bot API counterpart, the method can be used to send a set of inline results to the user; see the constructor page for more info on the MTProto method parameters ».

In general, the method accepts a vector of InputBotInlineResult constructors, that when chosen, generates a message with optionally attached media, and even inline buttons.

3. Sending the inline query result

botInlineMessageMediaAuto#764cf810 flags:# invert_media:flags.3?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true invert_media:flags.3?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaGeo#51846fd flags:# geo:GeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#18d1cdc2 flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;

botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;

messages.botResults#e021f2f6 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM switch_webview:flags.3?InlineBotWebView results:Vector<BotInlineResult> cache_time:int users:Vector<User> = messages.BotResults;

---functions---

messages.sendInlineBotResult#3ebee86a flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to:flags.0?InputReplyTo random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut = Updates;

The user client should display the messages.botResults.results obtained during querying in a list, making sure to handle eventual bot timeouts in the form of a BOT_RESPONSE_TIMEOUT RPC error, by simply not displaying anything.

If either the messages.botResults.switch_pm or messages.botResults.switch_webview flags are populated, a button should be displayed on top of the result list, that when clicked, instead of sending an inline result to the chat, switches the user to a private chat with the bot (switch_pm) or to a inline mode mini app (switch_webview).

If the user instead chooses a specific BotInlineResult from the normal results list, the messages.sendInlineBotResult method should be invoked, passing:

  • The query_id from messages.botResults
  • The id of the chosen result
  • The peer where to send the chosen result

The resulting message will have the via_bot_id field set, to indicate that the result was generated by the bot that generated the inline result.
Graphical clients should display the bot @username in the header of the message, allowing the user to click on it, automatically starting an inline query by inserting @username in the text bar.

4. Inline feedback

inputBotInlineMessageID#890c3d89 dc_id:int id:long access_hash:long = InputBotInlineMessageID;

updateBotInlineSend#12f12a07 flags:# user_id:long query:string geo:flags.0?GeoPoint id:string msg_id:flags.1?InputBotInlineMessageID = Update;

If feedback collection is enabled, the bot may receive an updateBotInlineSend when the user chooses and sends an inline result.

Even if the probability setting is set to 100%, not all inline results may be reported due to caching (see the cache_time parameter in Answering a callback query).
Feedback collection can also create load issues for popular bots, so adjust the probability setting to a lower value in such cases.

Either way, feedback collection should only be used for statistical purposes rather than functional.

The updateBotInlineSend will contain:

  • id - The ID of the chosen result
  • msg_id - The ID of the sent inline message
  • user_id - The ID of the user that chose the result
  • query - The query string that was used to obtain the result
  • geo - For bots requiring location-based inline results, the user's location

5. Editing sent inline messages

updateInlineBotCallbackQuery#691e9052 flags:# query_id:long user_id:long msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;

inputBotInlineMessageID#890c3d89 dc_id:int id:long access_hash:long = InputBotInlineMessageID;

---functions---

messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true invert_media:flags.16?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;

Sent inline messages can be edited by the bot, for example in response to a button press callback query.

Simply pass the inputBotInlineMessageID specified in the updateInlineBotCallbackQuery to messages.editInlineBotMessage along with the new message, making sure to send the query to the datacenter specified in inputBotInlineMessageID.dc_id.