How to Receive Telegram Updates Using Webhooks in Telego
To receive Telegram updates using webhooks in Telego, initialize a bot with NewBot, configure a webhook endpoint via SetWebhook or WithWebhookSet, attach a server handler (WebhookFastHTTP, WebhookHTTPServer, or WebhookHTTPServeMux) to UpdatesViaWebhook, and consume the returned channel to process Update structs.
The mymmrac/telego library provides a type-safe, high-performance Go SDK for the Telegram Bot API that supports webhook-based updates with minimal boilerplate. This approach delivers lower latency than long-polling by allowing Telegram to push updates directly to your HTTP server. Below is a complete technical guide to implementing webhooks using the actual source architecture.
Setting Up the Bot and Secret Token
Begin by creating a bot instance using NewBot in bot.go (lines 90-105). This validates your token and constructs a *telego.Bot with a default HTTP client.
bot, err := telego.NewBot(token, telego.WithDefaultDebugLogger())
if err != nil {
log.Fatal(err)
}
The library automatically generates a secret token for webhook security. Calling bot.SecretToken() returns a SHA-256 hash of your bot token (see bot.go lines 123-128), which you must provide to Telegram to verify incoming requests via the X-Telegram-Bot-Api-Secret-Token header.
Registering the Webhook with Telegram
You have two methods to register your endpoint with Telegram’s setWebhook API:
Manual registration using SetWebhook:
err := bot.SetWebhook(ctx, &telego.SetWebhookParams{
URL: "https://example.com/bot",
SecretToken: bot.SecretToken(),
})
Automatic registration using the WithWebhookSet option, which invokes SetWebhook immediately before the bot starts listening (see webhook.go lines 37-44):
updates, err := bot.UpdatesViaWebhook(
ctx,
handler,
telego.WithWebhookSet(ctx, &telego.SetWebhookParams{
URL: "https://example.com/bot",
SecretToken: bot.SecretToken(),
}),
)
Both approaches store your URL and secret token on Telegram’s servers, enabling the push mechanism.
Starting the Webhook Server
The core method UpdatesViaWebhook in webhook.go (lines 45-91) initializes the update channel and registers your HTTP handler. It enforces exclusive execution via run(runningWebhook) to prevent conflicts with long-polling (see bot.go lines 71-84).
Telego provides three handler factories in webhook_handler.go to accommodate different HTTP stacks:
Using FastHTTP
WebhookFastHTTP registers a POST handler on a fasthttp.Server (lines 13-45). This zero-allocation option offers the highest performance for high-throughput bots.
srv := &fasthttp.Server{}
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookFastHTTP(srv, "/bot", bot.SecretToken()),
telego.WithWebhookBuffer(128),
)
Using Standard HTTP
WebhookHTTPServer integrates with net/http.Server (lines 47-86) for standard library compatibility.
mux := http.NewServeMux()
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookHTTPServer(mux, "/bot", bot.SecretToken()),
)
Using ServeMux
WebhookHTTPServeMux works with http.ServeMux (lines 89-118), useful for combining multiple routes or existing HTTP multiplexers.
All handlers validate the HTTP method, request path, and secret token header. They return 500 Internal Server Error on processing failures or 200 OK on success.
Processing Incoming Updates
UpdatesViaWebhook returns a receive-only channel <-chan telego.Update backed by a buffered internal channel. The library unmarshals incoming JSON payloads into Update structs and pushes them to this channel.
Consume updates by ranging over the channel:
for update := range updates {
// Access update.Message, update.CallbackQuery, etc.
fmt.Printf("Received: %+v\n", update)
}
When the provided context is cancelled, the channel closes automatically and the bot’s running state resets (see the cleanup goroutine in webhook.go lines 84-89).
Complete Working Example
The following example mirrors the implementation in examples/updates_webhook/main.go, demonstrating FastHTTP integration with automatic webhook registration:
package main
import (
"context"
"fmt"
"os"
"github.com/valyala/fasthttp"
"github.com/mymmrac/telego"
)
func main() {
ctx := context.Background()
botToken := os.Getenv("TOKEN")
// Initialize bot with debug logging
bot, err := telego.NewBot(botToken, telego.WithDefaultDebugLogger())
if err != nil {
fmt.Println("Error creating bot:", err)
os.Exit(1)
}
// Optional: Verify webhook status
info, _ := bot.GetWebhookInfo(ctx)
fmt.Printf("Current webhook info: %+v\n", info)
// Configure FastHTTP server
srv := &fasthttp.Server{}
// Start webhook receiver with automatic registration
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookFastHTTP(srv, "/bot", bot.SecretToken()),
telego.WithWebhookBuffer(128),
telego.WithWebhookSet(ctx, &telego.SetWebhookParams{
URL: "https://example.com/bot",
SecretToken: bot.SecretToken(),
}),
)
if err != nil {
fmt.Println("Failed to start webhook:", err)
os.Exit(1)
}
// Run server in background
go func() {
if err := srv.ListenAndServe(":433"); err != nil {
fmt.Println("Server error:", err)
}
}()
// Process updates
for upd := range updates {
fmt.Printf("Update ID %d: %+v\n", upd.UpdateID, upd.Message)
}
}
For local development, expose your local port using ngrok or a similar tunneling service to provide a public HTTPS URL required by Telegram.
Summary
NewBotcreates the bot instance and generates a SHA-256 secret token viaSecretToken()inbot.go.UpdatesViaWebhookinwebhook.gomanages the update channel and ensures exclusive running state.- Three handler options exist:
WebhookFastHTTPfor high-performance FastHTTP,WebhookHTTPServerfor standard library, andWebhookHTTPServeMuxfor route multiplexing. - Registration flexibility allows manual
SetWebhookcalls or automatic configuration viaWithWebhookSet. - Security relies on the
X-Telegram-Bot-Api-Secret-Tokenheader validated againstbot.SecretToken(). - Update consumption uses a simple
for rangeloop over the channel returned byUpdatesViaWebhook.
Frequently Asked Questions
What is the difference between SetWebhook and WithWebhookSet?
SetWebhook is a manual API call that registers your endpoint immediately, while WithWebhookSet is an option passed to UpdatesViaWebhook that automatically invokes SetWebhook right before the bot starts listening. Use WithWebhookSet to ensure atomic registration and server startup, or use SetWebhook separately if you need to manage webhook configuration independently of the update loop.
Which webhook handler should I choose for production?
Choose WebhookFastHTTP if you require maximum performance and low latency, as it leverages valyala/fasthttp with zero-allocation request handling. Use WebhookHTTPServer or WebhookHTTPServeMux if you are already using Go’s standard net/http stack or need compatibility with existing HTTP middleware and routing libraries.
How does Telego verify webhook requests from Telegram?
Telego validates the X-Telegram-Bot-Api-Secret-Token header on every incoming request, comparing it against the value returned by bot.SecretToken() (a SHA-256 hash of your bot token). This verification occurs inside the handler factories in webhook_handler.go. If the header is missing or incorrect, the handler rejects the request before it reaches your update channel.
Can I use webhooks and long-polling simultaneously?
No, Telego enforces mutual exclusivity between update methods. The UpdatesViaWebhook method calls run(runningWebhook) in bot.go (lines 71-84), which checks the bot’s atomic running state and returns an error if another update source (such as UpdatesViaLongPolling) is already active. You must stop one method before starting the other.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →