First Webhook

Written by
Updated at June 10, 2026

Deployment checklist. This page explains why each step matters — copy-paste code is on the home page.

What changes from polling

Part Change
Handlers, routers, FSM None — move as-is
Process bootstrap Web framework + engine instead of start_polling()
Public URL Telegram must reach HTTPS
set_webhook() Registers that URL with Telegram
Security Verifies incoming requests at the public endpoint

Tip

Develop handlers with long polling locally; switch to webhooks for deployment. Only bootstrap code changes.

1. Handlers stay ordinary aiogram

from aiogram import Dispatcher, Router
from aiogram.filters import CommandStart
from aiogram.types import Message

router = Router()


@router.message(CommandStart())
async def start(message: Message) -> None:
    await message.answer("Webhook is alive")


dispatcher = Dispatcher()
dispatcher.include_router(router)

2. Wire engine and adapter

The engine connects dispatcher, bot, adapter, route, and security in one place — copy the minimal app from the home page.

Two registrations

Step Call Purpose
Local route + lifecycle engine.register(app) Registers POST route and wires engine startup/shutdown in your web framework.
Telegram delivery await engine.set_webhook() Tells Telegram the public HTTPS URL for future updates.

Run set_webhook() from framework startup after the endpoint is reachable. For TokenEngine, call add_bot(token) per bot instead.

Adapter-specific details: FastAPI · aiohttp

3. Expose a public HTTPS URL

Telegram delivers updates only over HTTPS to an internet-reachable host.

Environment Typical approach
Local development Tunnel (ngrok, cloudflared) or staging server
Production Reverse proxy (nginx, Caddy) or platform load balancer

Route(base_url=...) must match the public origin — scheme, host, and port if non-standard.

Warning

Do not use http://localhost in base_url unless Telegram can reach it. For local work, put the tunnel's HTTPS URL in base_url.

Checklist before set_webhook()

4. Register with Telegram

Call after the endpoint is reachable:

await engine.set_webhook()  # SingleBotEngine
await engine.add_bot("123456:ABCDEF")  # TokenEngine

The engine forwards WebhookConfig fields and the secret from Security, so Telegram registration and request verification stay aligned. Details: WebhookConfig.

How do I know Telegram accepted it?

set_webhook() returns True on success. Inspect live state:

info = await bot.get_webhook_info()
print(info.url, info.last_error_message)

Empty url or a set last_error_message means fix connectivity or TLS before debugging handlers.

5. Verify end-to-end

  1. Send /start in Telegram.
  2. Confirm the handler reply arrives.
  3. On failure, check Errors and application logs (aiogram_webhook logger).

Request flow diagram: Dispatch modes.

Where to go next

Topic Page
Secret token and IP checks Security
allowed_updates, drop_pending_updates WebhookConfig
Project file layout Single-bot app
Several bots on one service Multi-bot app
Previous