---
title: Telegram Webhook Integration in .NET
description: "Set up Telegram Bot API webhooks with ASP.NET Core—webhooks vs long polling, HTTPS, secret tokens, and production use cases."
image: "https://wavepillars.com/learn/telegram-og.webp"
url: "https://wavepillars.com/learn/engineering/telegram-webhook-integration-dotnet/"
---

When a Telegram bot runs in production, **long polling**—constantly asking Telegram "any new messages?"—works, but it is not ideal. **Webhooks** flip the model: Telegram **pushes** each update to your HTTPS endpoint as soon as it happens. That means lower latency, cleaner scaling behind a load balancer, and a bot that lives naturally inside an ASP.NET Core app alongside your REST APIs.

This guide shows how to integrate Telegram webhooks in .NET: when to choose them, what Telegram requires, a complete ASP.NET Core example, local development with a tunnel, and practical use cases.

**Prerequisite:** If you have not created a bot yet, start with [How to Build a Telegram Bot with C#](/learn/engineering/how-to-build-telegram-bot/) for BotFather setup and `Telegram.Bot` basics.

## Key Takeaways

- Register an HTTPS POST endpoint and call setWebhook with your public URL.
- Use Telegram's secret token header to reject forged webhook calls.
- Return 200 quickly; process heavy work asynchronously to avoid retries.
- Make update handlers idempotent—Telegram may deliver duplicates.
- Use long polling locally; webhooks need a valid public TLS certificate.

## What is a Telegram webhook?

With a webhook, you register a public **HTTPS URL** with Telegram. When a user sends a message, taps a button, or triggers any subscribed event, Telegram sends an **HTTP POST** to that URL with a JSON **`Update`** payload. Your server processes the update and calls the Bot API (for example `sendMessage`) to respond.

Your handler should return **200 OK** quickly. Telegram may retry if the response is slow or missing—design for idempotency when side effects matter.

## Webhook vs long polling

| Aspect | Long polling | Webhook |
|--------|--------------|---------|
| **Connection model** | Bot pulls updates (`getUpdates`) | Telegram pushes updates to your URL |
| **Hosting** | Any machine with outbound HTTPS | Public HTTPS URL required |
| **Latency** | Small poll interval delay | Near-instant delivery |
| **Scale** | One active poller per bot token | Stateless handlers behind a load balancer |
| **Local dev** | Simple (`dotnet run`) | Needs a tunnel (ngrok, Cloudflare Tunnel) |
| **Best for** | Prototyping, local testing | Production, alerts, multi-instance deploys |

The [long-polling guide](/learn/engineering/how-to-build-telegram-bot/) is the fastest way to get a bot running on your laptop. For 24/7 cloud deployment, **webhooks are the production default**.

## When to use webhooks

Use webhooks when:

- The bot runs **24/7** on Azure App Service, AWS, a VPS, or Kubernetes
- You need **low-latency** delivery—alerts, support replies, transactional notifications
- You want **horizontal scaling**: multiple app instances share one webhook URL behind a load balancer
- The bot is part of a **larger ASP.NET service**—same host as REST APIs, background jobs, or admin dashboards

Stick with long polling when you are prototyping locally and do not want to expose a public URL yet.

## Requirements

Before calling `setWebhook`, make sure you have:

1. **Valid HTTPS URL** — Telegram requires HTTPS with a trusted certificate. Self-signed certs are rejected in normal setups.
2. **Bot token** — from [@BotFather](https://t.me/BotFather). Load from environment variables, Azure Key Vault, or .NET user secrets—never commit tokens to source control.
3. **Secret token (recommended)** — a random string you pass to `setWebhook`. Telegram sends it back in the `X-Telegram-Bot-Api-Secret-Token` header so you can reject forged requests.
4. **Reverse proxy awareness** — if you terminate TLS at nginx, Azure Front Door, or Cloudflare, enable ASP.NET Core **Forwarded Headers** middleware so your app sees the correct scheme and client IP.

## Complete example: ASP.NET Core webhook bot

This echo bot mirrors the [long-polling tutorial](/learn/engineering/how-to-build-telegram-bot/) but uses webhooks and ASP.NET Core minimal APIs.

### Create the project

```bash
dotnet new web -n TelegramWebhookBot
cd TelegramWebhookBot
dotnet add package Telegram.Bot
```

Pin a local port in `Properties/launchSettings.json`:

```json
"applicationUrl": "http://localhost:5140"
```

### Configuration

Add to `appsettings.Development.json`:

```json
{
  "Telegram": {
    "BotToken": "YOUR_BOT_TOKEN_HERE"
  }
}
```

### Minimal API implementation

Update `Program.cs`:

```csharp
using System.Text.Json;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<ITelegramBotClient>(_ =>
{
    var token = builder.Configuration["Telegram:BotToken"]
        ?? throw new InvalidOperationException("Bot token missing");

    return new TelegramBotClient(token);
});

var app = builder.Build();

app.MapGet("/", () => "Telegram bot is running");

app.MapPost("/telegram/webhook", async (
    Update update,
    ITelegramBotClient botClient,
    ILogger<Program> logger) =>
{
    try
    {
        if (update.Type == UpdateType.Message &&
            update.Message?.Text is not null)
        {
            var chatId = update.Message.Chat.Id;
            var text = update.Message.Text;

            logger.LogInformation("Message received: {Text}", text);

            await botClient.SendMessage(
                chatId: chatId,
                text: $"Echo: {text}");
        }

        return Results.Ok();
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "Webhook processing failed");
        return Results.Problem();
    }
});

app.Run();
```

### How it works

- **`ITelegramBotClient`** — singleton client for Bot API calls (`SendMessage`, `SetWebhook`, etc.).
- **`MapPost("/telegram/webhook")`** — ASP.NET Core deserializes the JSON body into an `Update` automatically.

### Run API in cloud

Telegram cannot reach `http://localhost:5140` directly. Create Azure Web App and deploy your app there:

```bash
dotnet build

dotnet publish -c Release -o publish

cd publish

zip -r app.zip .

az webapp deploy \
  --resource-group rg \
  --name telegram-webhook \
  --src-path app.zip
```

## Register webhook in Telegram

Open browser:

```bash
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook?url=https://<YOUR_SERVER>/telegram/webhook
```

Telegram should return:

```bash
{
  "ok": true,
  "result": true
}
```

Webhook registration uses Telegram `setWebhook`.

## Test

Send a message to your bot in Telegram.

Your API receives:

```bash
{
  "update_id": 123456,
  "message": {
    "text": "hello"
  }
}
```

And replies:

```bash
Echo: hello
```

## Useful Telegram API endpoints

Set webhook:

```bash
https://api.telegram.org/bot<BOT_TOKEN>/setWebhook?url=<URL>
```

Get webhook info:

```bash
https://api.telegram.org/bot<BOT_TOKEN>/getWebhookInfo
```

Delete webhook:

```bash
https://api.telegram.org/bot<BOT_TOKEN>deleteWebhook
```

## Production checklist

- **Secrets** — store `BotToken` in Key Vault or environment variables, not `appsettings.json` in the repo.
- **Return 200 quickly** — offload heavy work (LLM calls, database writes, external APIs) to a background queue if processing takes more than a second or two.
- **Structured logging** — log `update.Id` and `chat.Id`; avoid dumping full message bodies in production logs.
- **Idempotency** — Telegram may retry failed deliveries; track processed update IDs if your handler has side effects.
- **TLS at the edge** — terminate HTTPS at your ingress; do not expose plain HTTP publicly.

## Use cases

Webhooks fit any scenario where Telegram is a **real-time notification or interaction channel** for your .NET backend.

1. **DevOps and SRE alerts** — CI pipeline failures, deployment status, and monitoring thresholds pushed to a team channel. Your ASP.NET app receives GitHub/Azure DevOps webhooks and forwards summaries to Telegram.
2. **Customer support bot** — inbound user messages arrive via webhook; your handler creates tickets in Jira, Zendesk, or a custom CRM and replies with a case number.
3. **E-commerce notifications** — order confirmed, shipped, and delivered updates triggered from your order service without a polling loop.
4. **Internal command bot** — `/deploy`, `/status`, or `/rollback` commands parsed in the webhook handler and routed to internal APIs on the same host.
5. **Payment and fintech alerts** — transaction confirmations and fraud flags delivered instantly; outbound API calls from the handler use proper auth and audit logging.
6. **IoT and edge alerts** — device offline or threshold breach events from your telemetry pipeline forwarded to on-call engineers in Telegram.
7. **Lead capture** — website form submission hits your API; the handler posts a formatted summary to a sales Telegram group.
8. **Multi-tenant SaaS** — one ASP.NET service hosts multiple bots on different webhook paths (`/telegram/webhook/{tenantId}`), each with its own token and secret.

Webhook-driven alerting is a common pattern in API monitoring products—push a failure notification the moment a health check fails instead of waiting for the next poll cycle.

## Troubleshooting

| Symptom | Likely cause |
|---------|--------------|
| `SetWebhook` returns an error | Invalid HTTPS certificate, URL not publicly reachable, or wrong port |
| No updates received | Webhook not registered, wrong `WebhookUrl`, or firewall blocking Telegram |
| `401 Unauthorized` on webhook | `SecretToken` mismatch between config and `SetWebhook` call |
| Duplicate replies | Both polling and webhook active, or multiple instances without idempotency |
| Slow or timing out | Handler does too much work synchronously—move to a background queue |
| Wrong scheme behind proxy | Missing `UseForwardedHeaders()` — Telegram sees HTTP instead of HTTPS |

Use `GetWebhookInfo` to inspect the registered URL, last error message, and pending update count:

```csharp
var info = await bot.GetWebhookInfo();
Console.WriteLine($"URL: {info.Url}, LastError: {info.LastErrorMessage}");
```

## Conclusion

Telegram webhooks turn your bot into a standard HTTP endpoint: Telegram pushes updates, your ASP.NET Core app handles them, and you scale like any other web service. Start with the echo example, tunnel locally for testing, then add secret token validation, background processing, and deployment behind HTTPS.

For the first bot and local prototyping, use [How to Build a Telegram Bot with C#](/learn/engineering/how-to-build-telegram-bot/) with long polling. When you deploy to the cloud, switch to webhooks with the pattern above.

## FAQ

### How do I set up Telegram webhooks in ASP.NET Core?

Expose a POST endpoint that accepts Telegram Update JSON, configure Telegram.Bot to use webhook mode with setWebhook pointing at your HTTPS URL, and register a secret token Telegram sends on each request. ASP.NET Core minimal APIs or controllers both work; return 200 quickly and process heavy work asynchronously so Telegram does not retry flooded updates.

### What HTTPS requirements does Telegram enforce for webhooks?

Telegram requires a valid TLS certificate from a public CA—self-signed certificates are rejected unless you use Telegram's certificate upload flow for special cases. The webhook URL must be reachable on ports 443, 80, 88, or 8443. Local development typically uses long polling or a tunneling tool until you deploy.

### How do I verify webhook requests are from Telegram?

Pass a secret_token when calling setWebhook; Telegram includes it in the X-Telegram-Bot-Api-Secret-Token header on each update. Reject requests missing or mismatching that header before parsing the body. This prevents arbitrary actors from posting fake updates to your endpoint.

### What happens if my webhook handler is too slow?

Telegram expects a quick HTTP 200; slow handlers cause retries and duplicate processing. Acknowledge immediately and queue work to a background service, outbox, or channel consumer. Design idempotent handlers so duplicate deliveries do not double-charge users or send repeated messages.

## Internal Links

- [How to Build a Telegram Bot with C#](/learn/engineering/how-to-build-telegram-bot/)
- [What should a software engineer know? Skills checklist & roadmap](/learn/engineering/software-engineer-knowledge-framework/)
- [Server-Sent Events (SSE) and EventSource](/learn/ai/server-sent-events-sse-eventsource/)
- [What is the MCP Protocol?](/learn/ai/what-is-mcp-server/)
- [What is technical debt?](/learn/engineering/what-is-technical-debt/)

```json
{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","headline":"Telegram Webhook Integration in .NET","description":"Set up Telegram Bot API webhooks with ASP.NET Core—webhooks vs long polling, HTTPS, secret tokens, and production use cases.","datePublished":"2026-05-22","dateModified":"2026-07-11","url":"https://wavepillars.com/learn/engineering/telegram-webhook-integration-dotnet/","author":{"@type":"Person","name":"Kiryl Bahdanovich"},"publisher":{"@type":"Organization","name":"WAVEPILLARS","url":"https://wavepillars.com/"},"image":"https://wavepillars.com/learn/telegram-og.webp","timeRequired":"PT14M"},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"How do I set up Telegram webhooks in ASP.NET Core?","acceptedAnswer":{"@type":"Answer","text":"Expose a POST endpoint that accepts Telegram Update JSON, configure Telegram.Bot to use webhook mode with setWebhook pointing at your HTTPS URL, and register a secret token Telegram sends on each request. ASP.NET Core minimal APIs or controllers both work; return 200 quickly and process heavy work asynchronously so Telegram does not retry flooded updates."}},{"@type":"Question","name":"What HTTPS requirements does Telegram enforce for webhooks?","acceptedAnswer":{"@type":"Answer","text":"Telegram requires a valid TLS certificate from a public CA—self-signed certificates are rejected unless you use Telegram's certificate upload flow for special cases. The webhook URL must be reachable on ports 443, 80, 88, or 8443. Local development typically uses long polling or a tunneling tool until you deploy."}},{"@type":"Question","name":"How do I verify webhook requests are from Telegram?","acceptedAnswer":{"@type":"Answer","text":"Pass a secret_token when calling setWebhook; Telegram includes it in the X-Telegram-Bot-Api-Secret-Token header on each update. Reject requests missing or mismatching that header before parsing the body. This prevents arbitrary actors from posting fake updates to your endpoint."}},{"@type":"Question","name":"What happens if my webhook handler is too slow?","acceptedAnswer":{"@type":"Answer","text":"Telegram expects a quick HTTP 200; slow handlers cause retries and duplicate processing. Acknowledge immediately and queue work to a background service, outbox, or channel consumer. Design idempotent handlers so duplicate deliveries do not double-charge users or send repeated messages."}}]}]}
```