# How to Receive Telegram Updates Using Webhooks in Telego

> Learn to receive Telegram updates with webhooks in Telego. Set up your bot, define an endpoint, attach a server handler, and process updates efficiently.

- Repository: [Artem Yadelskyi/telego](https://github.com/mymmrac/telego)
- Tags: how-to-guide
- Published: 2026-03-07

---

**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`](https://github.com/mymmrac/telego/blob/main/bot.go) (lines [90-105](https://github.com/mymmrac/telego/blob/main/bot.go#L90-L105)). This validates your token and constructs a `*telego.Bot` with a default HTTP client.

```go
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`](https://github.com/mymmrac/telego/blob/main/bot.go) lines [123-128](https://github.com/mymmrac/telego/blob/main/bot.go#L123-L128)), 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`:

```go
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`](https://github.com/mymmrac/telego/blob/main/webhook.go) lines [37-44](https://github.com/mymmrac/telego/blob/main/webhook.go#L37-L44)):

```go
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`](https://github.com/mymmrac/telego/blob/main/webhook.go) (lines [45-91](https://github.com/mymmrac/telego/blob/main/webhook.go#L45-L91)) 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`](https://github.com/mymmrac/telego/blob/main/bot.go) lines [71-84](https://github.com/mymmrac/telego/blob/main/bot.go#L71-L84)).

Telego provides three handler factories in [`webhook_handler.go`](https://github.com/mymmrac/telego/blob/main/webhook_handler.go) to accommodate different HTTP stacks:

### Using FastHTTP

**`WebhookFastHTTP`** registers a POST handler on a `fasthttp.Server` (lines [13-45](https://github.com/mymmrac/telego/blob/main/webhook_handler.go#L13-L45)). This zero-allocation option offers the highest performance for high-throughput bots.

```go
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](https://github.com/mymmrac/telego/blob/main/webhook_handler.go#L47-L86)) for standard library compatibility.

```go
mux := http.NewServeMux()
updates, err := bot.UpdatesViaWebhook(
    ctx,
    telego.WebhookHTTPServer(mux, "/bot", bot.SecretToken()),
)

```

### Using ServeMux

**`WebhookHTTPServeMux`** works with `http.ServeMux` (lines [89-118](https://github.com/mymmrac/telego/blob/main/webhook_handler.go#L89-L118)), 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:

```go
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`](https://github.com/mymmrac/telego/blob/main/webhook.go) lines [84-89](https://github.com/mymmrac/telego/blob/main/webhook.go#L84-L89)).

## Complete Working Example

The following example mirrors the implementation in [`examples/updates_webhook/main.go`](https://github.com/mymmrac/telego/blob/main/examples/updates_webhook/main.go), demonstrating FastHTTP integration with automatic webhook registration:

```go
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

- **`NewBot`** creates the bot instance and generates a SHA-256 secret token via `SecretToken()` in [`bot.go`](https://github.com/mymmrac/telego/blob/main/bot.go).
- **`UpdatesViaWebhook`** in [`webhook.go`](https://github.com/mymmrac/telego/blob/main/webhook.go) manages the update channel and ensures exclusive running state.
- **Three handler options** exist: `WebhookFastHTTP` for high-performance FastHTTP, `WebhookHTTPServer` for standard library, and `WebhookHTTPServeMux` for route multiplexing.
- **Registration flexibility** allows manual `SetWebhook` calls or automatic configuration via `WithWebhookSet`.
- **Security** relies on the `X-Telegram-Bot-Api-Secret-Token` header validated against `bot.SecretToken()`.
- **Update consumption** uses a simple `for range` loop over the channel returned by `UpdatesViaWebhook`.

## 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`](https://github.com/mymmrac/telego/blob/main/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`](https://github.com/mymmrac/telego/blob/main/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.