sendPoll
Use this method to send a native poll. On success, the sent Message is returned.
Parameters
business_connection_idStringOptionalUnique identifier of the business connection on behalf of which the message will be sent
chat_idIntegerStringRequiredUnique identifier for the target chat or username of the target bot, supergroup or channel in the format
@username. Polls can't be sent to channel direct messages chats.message_thread_idIntegerOptionalUnique identifier for the target message thread (topic) of a forum; for forum supergroups and private chats of bots with forum topic mode enabled only
Poll question, 1-300 characters
question_parse_modeStringOptionalMode for parsing entities in the question. See formatting options for more details. Currently, only custom emoji entities are allowed.
A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question\parse\mode.
A JSON-serialized list of 1-12 answer options
is_anonymousBooleanOptionalTrue, if the poll needs to be anonymous, defaults to True
typeStringOptionalValues:
quizregularPoll type, "quiz" or "regular", defaults to "regular"
allows_multiple_answersBooleanOptionalPass True, if the poll allows multiple answers, defaults to False
allows_revotingBooleanOptionalPass True, if the poll allows to change chosen answer options, defaults to False for quizzes and to True for regular polls
shuffle_optionsBooleanOptionalPass True, if the poll options must be shown in random order
allow_adding_optionsBooleanOptionalPass True, if answer options can be added to the poll after creation; not supported for anonymous polls and quizzes
hide_results_until_closesBooleanOptionalPass True, if poll results must be shown only after the poll closes
members_onlyBooleanOptionalPass True, if voting is limited to users who have been members of the chat where the poll is being sent for more than 24 hours; for channel chats only
country_codesString[]OptionalA JSON-serialized list of 0-12 two-letter ISO 3166-1 alpha-2 country codes indicating the countries from which users can vote in the poll; for channel chats only. Use "FT" as a country code to allow users with anonymous numbers to vote. If omitted or empty, then users from any country can participate in the poll.
correct_option_idsInteger[]OptionalA JSON-serialized list of monotonically increasing 0-based identifiers of the correct answer options, required for polls in quiz mode
Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing
explanation_parse_modeStringOptionalMode for parsing entities in the explanation. See formatting options for more details.
A JSON-serialized list of special entities that appear in the poll explanation. It can be specified instead of explanation\parse\mode.
Media added to the quiz explanation
open_periodIntegerOptionalAmount of time in seconds the poll will be active after creation, 5-2628000. Can't be used together with close\_date.
close_dateIntegerOptionalPoint in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 2628000 seconds in the future. Can't be used together with open\_period.
is_closedBooleanOptionalPass True if the poll needs to be immediately closed. This can be useful for poll preview.
Description of the poll to be sent, 0-1024 characters after entities parsing
description_parse_modeStringOptionalMode for parsing entities in the poll description. See formatting options for more details.
A JSON-serialized list of special entities that appear in the poll description, which can be specified instead of description\parse\mode
Media added to the poll description
disable_notificationBooleanOptionalSends the message silently. Users will receive a notification with no sound.
protect_contentBooleanOptionalProtects the contents of the sent message from forwarding and saving
allow_paid_broadcastBooleanOptionalPass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance.
message_effect_idStringOptionalUnique identifier of the message effect to be added to the message; for private chats only
Description of the message to reply to
reply_markupInlineKeyboardMarkupReplyKeyboardMarkupReplyKeyboardRemoveForceReplyOptional⌨️ KeyboardsAdditional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user.
Returns
On success, the Message object is returned.
GramIO Usage
ts
// Simple anonymous regular poll with 30-second timer
bot.command("poll", (ctx) =>
ctx.sendPoll({
question: "What is your favorite runtime?",
options: [
{ text: "Bun" },
{ text: "Node.js" },
{ text: "Deno" },
],
is_anonymous: false,
open_period: 30,
})
);ts
// Quiz mode with correct answer and explanation
bot.command("quiz", (ctx) =>
ctx.sendPoll({
question: "Which HTTP status code means 'Too Many Requests'?",
options: [
{ text: "400" },
{ text: "404" },
{ text: "429" },
{ text: "500" },
],
type: "quiz",
correct_option_ids: [2],
explanation: "429 is the standard rate-limit code defined in RFC 6585.",
is_anonymous: true,
})
);ts
// Multiple-choice poll that closes at a specific Unix timestamp
bot.command("multivote", (ctx) =>
ctx.sendPoll({
question: "Which features do you use? (pick all that apply)",
options: [
{ text: "Inline keyboards" },
{ text: "Scenes" },
{ text: "Sessions" },
{ text: "i18n" },
],
allows_multiple_answers: true,
close_date: Math.floor(Date.now() / 1000) + 300, // closes in 5 min
})
);ts
// Reply to a message with a poll and immediately stop it (useful for previews)
bot.command("preview", async (ctx) => {
const msg = await ctx.replyWithPoll({
question: "Draft poll — closed for preview",
options: [{ text: "Option A" }, { text: "Option B" }],
is_closed: true,
});
// msg.messageId is available on the returned MessageContext
return msg;
});Errors
| Code | Error | Cause |
|---|---|---|
| 400 | Bad Request: chat not found | Invalid or inaccessible chat_id — verify the chat exists and the bot is a member |
| 400 | Bad Request: POLL_OPTION_INVALID | Fewer than 2 or more than 12 options provided, or an option text is empty |
| 400 | Bad Request: POLL_ANSWERS_TOO_MUCH | More than 12 options in the options array |
| 400 | Bad Request: POLL_QUESTION_INVALID | question is empty or exceeds 300 characters |
| 400 | Bad Request: poll can't be sent to channel direct messages chats | Polls are not supported in channel direct message threads |
| 400 | Bad Request: POLL_OPTION_CORRECT_ID_INVALID | correct_option_id is out of range or used without type: "quiz" |
| 400 | Bad Request: can't use both open_period and close_date | open_period and close_date are mutually exclusive |
| 403 | Forbidden: bot was blocked by the user | The target user has blocked the bot |
| 403 | Forbidden: not enough rights | Bot lacks can_send_polls permission in the group/channel |
| 429 | Too Many Requests: retry after N | Flood control triggered — use the auto-retry plugin to handle this automatically |
Auto-retry for 429 errors
Install the @gramio/auto-retry plugin to transparently handle flood-wait errors without manual retry logic.
Tips & Gotchas
- 2–12 options are required. Sending fewer than 2 or more than 12
InputPollOptionobjects throws aPOLL_OPTION_INVALIDerror. Each option'stextmust be 1–100 characters. - Quiz mode requires
correct_option_id. Omitting it whentype: "quiz"is set causes a 400 error. The ID is 0-based (first option =0). open_periodandclose_dateare mutually exclusive. Use one or the other. Both valid ranges map to 5–600 seconds from the time of sending.- Polls are anonymous by default. Set
is_anonymous: falseto make votes public. This cannot be changed after the poll is created. - Multiple answers are not allowed in quiz mode.
allows_multiple_answers: trueis silently ignored whentype: "quiz"is set. - Stop a poll later with
stopPoll. Usectx.stopPoll(messageId)to close a poll early and receive the final Poll object with vote counts.
See Also
- stopPoll — Close an active poll and retrieve final results
- Poll — The Poll type returned inside the Message
- PollAnswer — Update received when a user votes
- InputPollOption — Structure of each answer option
- sendMessage — Send a plain text message
- sendLocation — Send a location pin
- sendContact — Send a contact card
- Formatting guide — Format text using GramIO's
formattagged template