ptgb
A complete Telegram Bot API client for Dart

Polling vs. Webhooks

Telegram delivers updates through exactly one channel at a time — poll() and serveWebhook() are mutually exclusive. Pick one per bot process.

Long polling — Bot.poll()

Simplest option. No public URL, no TLS certificate, works behind NAT/localhost. Good default for development and small bots.

await for (final update in bot.poll()) {
  if (update.text == '/start') {
    await bot.sendMessage(update.chatId!, 'Hi!');
  }
}

Internally this repeatedly calls getUpdates, so if you’ve previously configured a webhook you should call deleteWebhook first — Telegram won’t deliver updates to getUpdates while a webhook is active.

Webhooks — Bot.serveWebhook()

Production-style: Telegram pushes updates to an HTTPS URL you control, and serveWebhook runs a local HTTP server to receive them.

Typical flow:

  1. Start your server: await bot.serveWebhook(...).
  2. Register the public URL with Telegram: await bot.setWebhook(...).
  3. When you want to go back to polling, call await bot.deleteWebhook() first.

Use getWebhookInfo() at any time to check what Telegram currently has registered (URL, pending update count, last error, etc).

Which should I use?

Polling Webhook
Public HTTPS URL required No Yes
Good for local development Yes Needs a tunnel (ngrok, etc)
Good for production at scale Workable, but less efficient Yes — Telegram pushes only when there’s something to deliver
Setup complexity Minimal Requires setWebhook + a reachable server

Example

See example/10_webhook_server.dart for a full runnable webhook setup, and example/01_basic_echo_bot.dart / example/02_commands_and_text.dart for polling.

Filtering update types

Both getUpdates (used internally by poll()) and setWebhook accept an allowedUpdates list built from the UpdateType enum, so you only receive the update kinds your bot actually handles (e.g. just message and callbackQuery).