Skip to content

answerWebAppQuery

Use this method to set the result of an interaction with a Web App and send a corresponding message on behalf of the user to the chat from which the query originated. On success, a SentWebAppMessage object is returned.

Parameters

web_app_query_idStringRequired
Unique identifier for the query to be answered
resultInlineQueryResultRequired
A JSON-serialized object describing the message to be sent

Returns

On success, the SentWebAppMessage object is returned.

GramIO Usage

typescript
import { Bot } from "gramio";

const bot = new Bot(process.env.BOT_TOKEN as string);

// Basic usage — answer a Web App query with an article result
bot.on("message", async (ctx) => {
  // web_app_query_id comes from the Web App via initData or postMessage
  const queryId = ctx.message.web_app_data?.web_app_query_id;
  if (!queryId) return;

  const result = await bot.api.answerWebAppQuery({
    web_app_query_id: queryId,
    result: {
      type: "article",
      id: "result-1",
      title: "Selected Item",
      input_message_content: {
        message_text: "You selected: Item #1",
      },
    },
  });

  // result.inline_message_id can be used to edit the sent message later
  console.log("Sent message ID:", result.inline_message_id);
});

// Answering with a photo result
bot.on("message", async (ctx) => {
  const queryId = ctx.message.web_app_data?.web_app_query_id;
  if (!queryId) return;

  await bot.api.answerWebAppQuery({
    web_app_query_id: queryId,
    result: {
      type: "photo",
      id: "photo-result-1",
      photo_url: "https://example.com/photo.jpg",
      thumbnail_url: "https://example.com/photo_thumb.jpg",
      caption: "Photo from Web App",
    },
  });
});

Errors

CodeErrorCause
400Bad Request: QUERY_ID_INVALIDweb_app_query_id has expired or was already answered — call this method once and promptly after the Web App sends the query
400Bad Request: query is too oldThe Web App query was not answered within its validity window — answer immediately upon receiving the query ID
400Bad Request: result id is not uniqueTwo results share the same id — ensure every result in results has a unique ID
403Forbidden: bot is not a memberThe bot that owns the token does not match the bot that served the Web App — ensure the correct bot token is used
429Too Many Requests: retry after NRate limit hit — inspect the retry_after field and use the auto-retry plugin

Tips & Gotchas

  • This method is for Web App (Mini App) interactions only. The web_app_query_id is generated by Telegram when a user interacts with a Web App attached to an inline keyboard or menu button. It is delivered via web_app_data on the server or via postMessage in the Mini App frontend.
  • Can only be answered once. Attempting to call answerWebAppQuery a second time with the same web_app_query_id returns QUERY_ID_INVALID. Cache your result if you need to reference it later.
  • The returned inline_message_id allows later edits. Store result.inline_message_id if you plan to update the sent message later using editMessageText, editMessageMedia, etc.
  • Not the same as answerInlineQuery. answerInlineQuery responds to a user typing @botname in any chat. answerWebAppQuery responds to an interaction triggered from a Web App within a bot.
  • Result type must match the intended content. Use "article" for text content, "photo" for images, etc. Invalid or mismatched result types cause a 400 error.
  • No parse_mode needed alongside format. When using GramIO's format tagged template to build message_text with entities, do not also pass parse_mode — the entities are already embedded.

See Also