Skip to main content
The Telegrator.Hosting.Web package enables you to build Telegram bots as ASP.NET Core applications with webhook support for receiving updates.

Installation

dotnet add package Telegrator.Hosting.Web

Quick Start

1

Configure webhook options

Create a TelegramBotWebOptions instance with your webhook URL:
using Telegrator.Hosting.Web;

var options = new TelegramBotWebOptions
{
    WebhookUri = "https://yourdomain.com/api/telegram",
    SecretToken = "your-secret-token"
};
The webhook URL must be HTTPS and publicly accessible. Telegram will send updates to this endpoint.
2

Create the web host builder

Use TelegramBotWebHost.CreateBuilder() with your options:
var builder = TelegramBotWebHost.CreateBuilder(options);
This automatically:
  • Configures ASP.NET Core web application
  • Registers Telegrator services
  • Sets up webhook endpoint routing
3

Register handlers

Add your update handlers to the Handlers collection:
builder.Handlers.AddHandler<StartCommandHandler>();
builder.Handlers.AddHandler<MessageHandler>();
4

Build and run

Build the host and start the web server:
var app = builder.Build();
await app.RunAsync();

Complete Example

Program.cs
using Telegrator.Hosting.Web;
using Telegrator.Sessions;
using Telegram.Bot.Types;
using Telegram.Bot;

// Configure webhook options
var options = new TelegramBotWebOptions
{
    WebhookUri = "https://yourdomain.com/api/telegram",
    SecretToken = "my-secret-token-123",
    MaxConnections = 40,
    DropPendingUpdates = false
};

// Create web host builder
var builder = TelegramBotWebHost.CreateBuilder(options);

// Configure bot token
builder.Configuration["TelegramBotClientOptions:Token"] = 
    Environment.GetEnvironmentVariable("BOT_TOKEN");

// Register handlers
builder.Handlers.AddHandler<StartCommandHandler>();
builder.Handlers.AddHandler<EchoMessageHandler>();

// Add additional endpoints (optional)
var app = builder.Build();

app.MapGet("/", () => "Bot is running!");
app.MapGet("/health", () => Results.Ok(new { status = "healthy" }));

// Run the application
await app.RunAsync();

// Handler examples
public class StartCommandHandler : IUpdateHandler
{
    public UpdateType AllowedUpdates => UpdateType.Message;

    public async Task HandleUpdateAsync(
        ITelegramBotClient client,
        Update update,
        CancellationToken ct)
    {
        if (update.Message?.Text == "/start")
        {
            await client.SendMessage(
                chatId: update.Message.Chat.Id,
                text: "Welcome to the bot!",
                cancellationToken: ct);
        }
    }
}

public class EchoMessageHandler : IUpdateHandler
{
    public UpdateType AllowedUpdates => UpdateType.Message;

    public async Task HandleUpdateAsync(
        ITelegramBotClient client,
        Update update,
        CancellationToken ct)
    {
        if (update.Message?.Text != null)
        {
            await client.SendMessage(
                chatId: update.Message.Chat.Id,
                text: $"Echo: {update.Message.Text}",
                cancellationToken: ct);
        }
    }
}

Builder Methods

The TelegramBotWebHost class provides several static factory methods:

CreateBuilder(options)

Creates a standard web application builder with default services:
public static TelegramBotWebHostBuilder CreateBuilder(
    TelegramBotWebOptions options)
Automatically:
  • Configures ASP.NET Core with default middleware
  • Adds logging providers
  • Registers Telegrator services
  • Sets up webhook receiver

CreateSlimBuilder(options)

Creates a minimal builder with fewer default services:
public static TelegramBotWebHostBuilder CreateSlimBuilder(
    TelegramBotWebOptions options)
Use this for:
  • Smaller deployment size
  • Faster startup time
  • When you don’t need full ASP.NET Core features

CreateEmptyBuilder(options)

Creates a builder without any default services:
public static TelegramBotWebHostBuilder CreateEmptyBuilder(
    TelegramBotWebOptions options)
Use this only if you need full control. You’ll need to manually register all required services.

Webhook Configuration

TelegramBotWebOptions

Configure webhook behavior when creating the builder:
var options = new TelegramBotWebOptions
{
    // Required: HTTPS URL for receiving updates
    WebhookUri = "https://yourdomain.com/api/telegram",
    
    // Optional: Secret token for webhook validation
    SecretToken = "your-secret-token",
    
    // Optional: Maximum concurrent connections (1-100)
    MaxConnections = 40,
    
    // Optional: Drop pending updates on startup
    DropPendingUpdates = false,
    
    // Optional: Web application settings
    ApplicationName = "MyTelegramBot",
    EnvironmentName = "Production"
};
WebhookUri
string
required
HTTPS URL to send updates to. Must be publicly accessible. The path component will be used as the endpoint route.
SecretToken
string
Secret token (1-256 characters) sent in X-Telegram-Bot-Api-Secret-Token header. Validates requests are from your webhook.
MaxConnections
int
default:"40"
Maximum simultaneous HTTPS connections to the webhook (1-100). Lower values limit load, higher values increase throughput.
DropPendingUpdates
bool
default:"false"
If true, drops all pending updates when the webhook is set.

Additional Configuration

Configure bot token and Telegrator options:
{
  "TelegramBotClientOptions": {
    "Token": "YOUR_BOT_TOKEN"
  },
  "TelegratorWebOptions": {
    "WebhookUri": "https://yourdomain.com/api/telegram",
    "SecretToken": "your-secret-token",
    "MaxConnections": 40,
    "DropPendingUpdates": false
  }
}

How Webhooks Work

When the application starts, the HostedUpdateWebhooker service:
  1. Extracts the path from your WebhookUri (e.g., /api/telegram)
  2. Automatically maps a POST endpoint at that path
  3. Calls SetWebhook on the Telegram API with your URL
  4. Validates incoming requests using the secret token (if configured)
  5. Deserializes the update and routes it to your handlers
HostedUpdateWebhooker.cs (simplified)
private async void StartInternal(CancellationToken cancellationToken)
{
    // Extract path from webhook URI
    string pattern = new UriBuilder(_options.WebhookUri).Path;
    
    // Map POST endpoint
    _botHost.MapPost(pattern, (Delegate)ReceiveUpdate);

    // Register webhook with Telegram
    await _botClient.SetWebhook(
        url: _options.WebhookUri,
        maxConnections: _options.MaxConnections,
        allowedUpdates: _botHost.UpdateRouter.HandlersProvider.AllowedTypes,
        dropPendingUpdates: _options.DropPendingUpdates,
        cancellationToken: cancellationToken);
}

ITelegramBotWebHost Interface

The web host implements multiple interfaces:
public interface ITelegramBotWebHost : 
    ITelegramBotHost,        // Bot functionality
    IEndpointRouteBuilder,   // ASP.NET Core routing
    IApplicationBuilder,     // Middleware pipeline
    IAsyncDisposable         // Async disposal
{
}
This allows you to:
  • Access bot services via ITelegramBotHost
  • Map additional endpoints via IEndpointRouteBuilder
  • Add middleware via IApplicationBuilder

Adding Custom Endpoints

Since the host implements IEndpointRouteBuilder, you can add standard ASP.NET Core endpoints:
var app = builder.Build();

// Health check endpoint
app.MapGet("/health", () => Results.Ok(new 
{ 
    status = "healthy",
    timestamp = DateTime.UtcNow 
}));

// Status endpoint with dependency injection
app.MapGet("/status", (ITelegramBotClient client) => 
{
    return Results.Ok(new 
    { 
        botId = client.BotId,
        running = true 
    });
});

// Protected admin endpoint
app.MapPost("/admin/broadcast", async (
    BroadcastRequest request,
    ITelegramBotClient client) =>
{
    // Send message to all users
    // Implementation here...
});

await app.RunAsync();

Adding Middleware

You can add ASP.NET Core middleware to the pipeline:
var app = builder.Build();

// Add CORS
app.UseCors(policy => policy
    .AllowAnyOrigin()
    .AllowAnyMethod()
    .AllowAnyHeader());

// Add request logging
app.Use(async (context, next) =>
{
    Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
    await next();
});

// Add authentication (for custom endpoints)
app.UseAuthentication();
app.UseAuthorization();

await app.RunAsync();

Service Registration

Register services like any ASP.NET Core application:
// Add MVC/Controllers if needed
builder.Services.AddControllers();

// Add database context
builder.Services.AddDbContext<BotDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

// Add custom services
builder.Services.AddSingleton<IUserRepository, UserRepository>();
builder.Services.AddScoped<IMessageService, MessageService>();

// Add HTTP clients
builder.Services.AddHttpClient();

// Add caching
builder.Services.AddMemoryCache();
builder.Services.AddDistributedMemoryCache();

Deployment Considerations

Telegram requires webhooks to use HTTPS. Ensure your deployment provides:
  • Valid SSL/TLS certificate (Let’s Encrypt, purchased cert, etc.)
  • Certificate from a trusted CA
  • TLS 1.2 or higher
For development, use a tunnel service like ngrok:
ngrok http 5000
# Use the HTTPS URL provided by ngrok
Your webhook endpoint must be publicly accessible:
  • No firewall blocking Telegram IPs
  • DNS properly configured
  • Port 443 or 8443 recommended
  • No authentication required on the webhook path
Always use a secret token in production:
var options = new TelegramBotWebOptions
{
    WebhookUri = "https://yourdomain.com/api/telegram",
    SecretToken = Environment.GetEnvironmentVariable("WEBHOOK_SECRET")
};
The token is sent in the X-Telegram-Bot-Api-Secret-Token header and validated automatically.
The webhook is automatically registered on application startup. To manually check or update:
var client = app.Services.GetRequiredService<ITelegramBotClient>();

// Get current webhook info
var info = await client.GetWebhookInfo();
Console.WriteLine($"Webhook URL: {info.Url}");
Console.WriteLine($"Pending updates: {info.PendingUpdateCount}");

// Delete webhook (switch to polling)
await client.DeleteWebhook();
Adjust MaxConnections based on your server capacity:
var options = new TelegramBotWebOptions
{
    WebhookUri = "https://yourdomain.com/api/telegram",
    MaxConnections = 100  // Higher for better throughput
};
Also configure Telegrator options:
var options = new TelegramBotWebOptions
{
    // ... webhook config ...
    MaximumParallelWorkingHandlers = 10  // Concurrent handler execution
};

Environment-Specific Configuration

Use different webhook URLs per environment:
var webhookUri = builder.Environment.IsDevelopment()
    ? "https://dev-tunnel.ngrok.io/api/telegram"
    : "https://production.yourdomain.com/api/telegram";

var options = new TelegramBotWebOptions
{
    WebhookUri = webhookUri,
    SecretToken = builder.Configuration["Webhook:SecretToken"],
    DropPendingUpdates = builder.Environment.IsDevelopment()
};

var builder = TelegramBotWebHost.CreateBuilder(options);

Logging

Configure logging for webhook diagnostics:
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();

if (builder.Environment.IsProduction())
{
    builder.Logging.AddApplicationInsights();
}

builder.Logging.SetMinimumLevel(LogLevel.Information);
Enable Telegrator internal logging:
var app = builder.Build();
app.AddLoggingAdapter();
await app.RunAsync();

Error Handling

The webhook endpoint automatically handles:
  • Secret token validation (401 if mismatch)
  • Malformed JSON (400 bad request)
  • Invalid update objects (400 bad request)
  • Handler exceptions (logged, returns 200 to Telegram)
Add global exception handling middleware:
app.Use(async (context, next) =>
{
    try
    {
        await next();
    }
    catch (Exception ex)
    {
        var logger = context.RequestServices
            .GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "Unhandled exception");
        
        context.Response.StatusCode = 500;
        await context.Response.WriteAsJsonAsync(new 
        { 
            error = "Internal server error" 
        });
    }
});

Best Practices

Use HTTPS

Always use HTTPS in production. Use ngrok or similar for local development.

Validate Requests

Always set a SecretToken to verify requests come from Telegram.

Monitor Webhooks

Regularly check webhook status with GetWebhookInfo().

Handle Errors

Return 200 OK even on errors to prevent Telegram from retrying.

Next Steps

Handlers

Learn how to create update handlers

Console Apps

Use long polling for development

Build docs developers (and LLMs) love