Multi-bot App
Use this recipe when many bots share one application and each webhook URL includes a bot token. The important difference from a single-bot app is that the route selects the bot.
Component Choices
| Need | Component |
|---|---|
| Many token-based bots | TokenEngine |
| Token in URL | Route with BotTokenParam |
| Bot creation defaults | BotConfig |
| Shared framework endpoint | FastAPIAdapter or AiohttpAdapter |
| Shared Telegram defaults | Engine-level WebhookConfig |
| Per-bot Telegram options | add_bot(..., webhook_config=...) |
Route Shape
from aiogram_webhook.route import BotTokenParam, Route
route = Route(
base_url="https://example.com",
path="/telegram/{bot_token}",
params={"bot_token": BotTokenParam()},
)
The route builds URLs like:
https://example.com/telegram/123456%3AABCDEF
Engine Setup
from aiogram import Dispatcher
from aiogram_webhook import BotConfig, FastAPIAdapter, TokenEngine, WebhookConfig
from aiogram_webhook.security import Security, StaticSecretToken
dispatcher = Dispatcher()
engine = TokenEngine(
dispatcher,
web=FastAPIAdapter(),
route=route,
bot_config=BotConfig(default=None),
webhook_config=WebhookConfig(allowed_updates=["message"]),
security=Security(secret_token=StaticSecretToken("webhook-secret")),
)
Add Bots
await engine.add_bot("123456:ABCDEF")
await engine.add_bot("654321:UVWXYZ")
add_bot() resolves the bot ID from the token, creates or reuses a Bot, builds the public webhook URL, and calls Telegram setWebhook.
Combine Per-bot Options
await engine.add_bot(
"123456:ABCDEF",
webhook_config=WebhookConfig(allowed_updates=["message"]),
)
Engine-level WebhookConfig is the default. Per-bot config is the override.
Remove Bots
await engine.remove_bot(
bot_id=123456,
delete_webhook=True,
drop_pending_updates=True,
)
Warning
If delete_webhook=False, do not pass drop_pending_updates.
The engine raises ValueError because Telegram accepts drop_pending_updates only with webhook deletion.
Operational Notes
| Topic | Recommendation |
|---|---|
| Token in path | Treat access logs as sensitive because token values may appear in URLs. |
| Shared session | Provide BotConfig(session=...) when you want to own session lifecycle. |
| Startup hooks | Dispatcher startup receives bots, the set of bots known at startup. |
| New bots | Bots can be created lazily on incoming requests or explicitly through add_bot(). |
Previous
Next