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