ptgb
A complete Telegram Bot API client for Dart

Configuration

Everything about a Bot is configured through its factory constructor:

factory Bot({
  String? token,
  String dotFileName = '.env',
  String envKey = 'TOKEN',
  String? apiBaseUrl,
  String? fileBaseUrl,
  RateLimiter? rateLimiter,
  Duration requestTimeout = const Duration(seconds: 35),
})
TOKEN=123456:ABC-your-token-here
final bot = Bot(); // reads TOKEN from .env

This is handled by the penv package under the hood. Add .env to .gitignore so it’s never committed.

Custom file name or key

final bot = Bot(dotFileName: 'secrets.env', envKey: 'BOT_TOKEN');

Passing the token directly

If you’re managing the token yourself — e.g. pulling it from a secrets manager at deploy time — skip .env entirely:

final bot = Bot(token: myTokenFromSomewhereElse);

Never hard-code a real token as a string literal in code that ends up in version control, either way.

Pointing at a self-hosted Bot API server

If you run your own Telegram Bot API server instead of using api.telegram.org, override the base URLs:

final bot = Bot(
  token: myToken,
  apiBaseUrl: 'https://my-bot-api.example.com/bot$myToken',
  fileBaseUrl: 'https://my-bot-api.example.com/file/bot$myToken',
);

Automatic rate limiting

Pass a RateLimiter to have ptgb pace outgoing requests for you, instead of handling 429 Too Many Requests yourself:

final bot = Bot(
  rateLimiter: RateLimiter(
    globalPerSecond: 30,
    perChatPerMinute: 20,
  ),
);

globalPerSecond throttles the bot's overall request rate; perChatPerMinute throttles requests to any single chat. Both are optional — pass only the one(s) you need, or skip rateLimiter entirely to keep the previous (unthrottled) behavior. See example/17_rate_limiting.dart for a runnable version.

Request timeout

requestTimeout controls how long a single HTTP call to Telegram is allowed to run before it's aborted, applied on top of the timeout seconds you pass to poll. It defaults to 35 seconds, which already leaves 5 seconds of headroom over poll's default 30-second long-poll timeout:

final bot = Bot(requestTimeout: const Duration(seconds: 60));

If you raise poll's timeout parameter, raise requestTimeout to match (or exceed it), or every long-poll call will time out before Telegram gets a chance to respond.

Shutting down

Call bot.dispose() when your process is shutting down for good, to release the underlying HTTP client’s resources.

See also: example/16_custom_env_config.dart in the package for a runnable version of the custom-.env setup above.