Interactive Polls & Quizzes (sendPoll & poll_answer)
Create regular voting polls, educational trivia quizzes with explanations, timer deadlines, and process live voting updates.
Interactive Polls & Trivia Quizzes Overview
Telegram polls allow bots to engage communities, run democratic elections, or administer educational quizzes with instant correct/wrong animations and confetti. Poll updates arrive via the poll_answer webhook object.
1. Creating Regular Polls vs. Quiz Mode
| Poll Type | Key Parameters | Behavior in Telegram |
|---|---|---|
| Regular Poll | type => 'regular', allows_multiple_answers, is_anonymous |
Standard public or anonymous voting. Users can retract or change their vote unless poll is closed. |
| Quiz Mode | type => 'quiz', correct_option_id, explanation |
Users choose once. Correct answer triggers celebratory confetti; wrong answer displays the explanation tooltip. |
PHP — Creating Regular and Quiz Polls
<?php
// ── Botlify Cloud .env — auto-injected, never hardcode secrets ──
$BOT_TOKEN = getenv('BOT_TOKEN'); // Telegram bot token from @BotFather
$ADMIN_CHAT_ID = getenv('ADMIN_CHAT_ID'); // Your numeric admin Telegram user ID
$BOT_USERNAME = getenv('BOT_USERNAME'); // Bot username without @
declare(strict_types=1);
// 1. Send Public Multiple-Choice Poll
function send_community_poll(string|int $chatId): void {
bot('sendPoll', [
'chat_id' => $chatId,
'question' => 'Which feature should Botlify Cloud build next?',
'options' => json_encode([
['text' => '⚡ Edge CDN Webhooks'],
['text' => '📱 Native iOS/Android SDK'],
['text' => '🧠 Autonomous Agent Swarms'],
['text' => '📊 Advanced Analytics Dashboard']
]),
'is_anonymous' => false, // Vote identities visible to admins
'allows_multiple_answers' => true,
'open_period' => 86400 // Automatically closes after 24 hours
]);
}
// 2. Send Educational Trivia Quiz with Explanation
function send_developer_quiz(string|int $chatId): void {
bot('sendPoll', [
'chat_id' => $chatId,
'question' => 'What is the default SQLite journal mode used by Botlify Cloud?',
'options' => json_encode([
['text' => 'DELETE (Default Rollback)'],
['text' => 'WAL (Write-Ahead Logging)'],
['text' => 'MEMORY Mode'],
['text' => 'OFF (No Journaling)']
]),
'type' => 'quiz',
'correct_option_id' => 1, // 0-indexed: Option 1 (WAL) is correct
'explanation' => 'Botlify Cloud runs SQLite in WAL (Write-Ahead Logging) mode with a 32MB cache to achieve 20ms concurrent reads and writes.',
'explanation_parse_mode' => 'HTML',
'is_anonymous' => true
]);
}
2. Stopping / Closing a Poll Programmatically
When a contest ends or voting deadline arrives, freeze the poll using stopPoll:
PHP — Freezing Polls with stopPoll
<?php
// ── Botlify Cloud .env — auto-injected, never hardcode secrets ──
$BOT_TOKEN = getenv('BOT_TOKEN'); // Telegram bot token from @BotFather
$ADMIN_CHAT_ID = getenv('ADMIN_CHAT_ID'); // Your numeric admin Telegram user ID
$BOT_USERNAME = getenv('BOT_USERNAME'); // Bot username without @
declare(strict_types=1);
$result = bot('stopPoll', [
'chat_id' => $chatId,
'message_id' => $pollMessageId
]);
if ($result['ok'] ?? false) {
$finalPoll = $result['result'];
$totalVoters = $finalPoll['total_voter_count'];
error_log("Poll closed. Total voters: {$totalVoters}");
}
3. Handling Live poll_answer Webhook Updates
When a user casts or changes a vote in a non-anonymous poll, Telegram dispatches a poll_answer update to your webhook:
PHP — Capturing and Storing poll_answer Updates
<?php
// ── Botlify Cloud .env — auto-injected, never hardcode secrets ──
$BOT_TOKEN = getenv('BOT_TOKEN'); // Telegram bot token from @BotFather
$ADMIN_CHAT_ID = getenv('ADMIN_CHAT_ID'); // Your numeric admin Telegram user ID
$BOT_USERNAME = getenv('BOT_USERNAME'); // Bot username without @
declare(strict_types=1);
if (isset($update['poll_answer'])) {
$answer = $update['poll_answer'];
$pollId = $answer['poll_id'];
$userId = $answer['user']['id'];
$userName = $answer['user']['first_name'] ?? 'User';
$selected = $answer['option_ids']; // Array of selected option indices e.g. [1]
if (empty($selected)) {
// User retracted their vote
$pdo->prepare("DELETE FROM poll_votes WHERE poll_id = ? AND user_id = ?")
->execute([$pollId, $userId]);
} else {
// Record or update vote in SQLite database.db
$stmt = $pdo->prepare("
INSERT INTO poll_votes (poll_id, user_id, chosen_option, voted_at)
VALUES (?, ?, ?, ?)
ON CONFLICT(poll_id, user_id) DO UPDATE SET chosen_option = excluded.chosen_option, voted_at = excluded.voted_at
");
$stmt->execute([$pollId, $userId, $selected[0], time()]);
// Optionally send a private reward message to the voter
bot('sendMessage', [
'chat_id' => $userId,
'text' => "🎉 Thanks for voting in our poll, {$userName}! +50 XP awarded.",
'parse_mode' => 'HTML'
]);
}
http_response_code(200);
exit;
}
Botlify Cloud Runtime
Credentials are auto-injected in
Credentials are auto-injected in
.env — always load them with getenv(): BOT_TOKEN, ADMIN_CHAT_ID, BOT_USERNAME. Main database: database.db (SQLite, WAL mode). Runtime errors: error.log. Quick test: send to $ADMIN_CHAT_ID. Full details: Runtime Reference.