How to Configure and Enable the FastAPI Webhook API Server in Claude Code Telegram

Set ENABLE_API_SERVER=true and API_SERVER_PORT=9000 in your environment variables to activate the FastAPI webhook server alongside the Telegram bot.

The Claude Code Telegram bot (RichardAtCT/claude-code-telegram) includes an optional FastAPI webhook API server that listens for external events from services like GitHub. When you configure and enable the FastAPI webhook API server, it runs concurrently with the bot on a configurable TCP port, publishing incoming webhooks to the internal EventBus for asynchronous processing.

Configuration Settings and Feature Flags

The server behavior is controlled through Pydantic settings defined in src/config/settings.py and exposed via feature flags in src/config/features.py.

Enable API Server Flag

The enable_api_server boolean field determines whether the FastAPI application starts during bot initialization.


# src/config/settings.py

enable_api_server: bool = Field(False, description="Enable FastAPI webhook server")

This value is accessed at runtime through FeatureFlags.api_server_enabled in src/config/features.py (lines 60-63), which the main application loop checks before spawning the server task.

Port Configuration

The api_server_port field specifies the TCP port that Uvicorn binds to.


# src/config/settings.py – default value 8080

api_server_port: int = Field(8080, description="Webhook API server port")

If the port is already in use, the application will raise a OSError during startup, so ensure the chosen port is available in your environment.

Enabling the Server via Environment Variables

The Settings class loads configuration from environment variables or an optional .env file (configured via env_file=".env"). To enable the webhook server on a custom port, add the following to your environment:

TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
APPROVED_DIRECTORY=/home/user/projects
ENABLE_API_SERVER=true
API_SERVER_PORT=9000

# Optional: secure your webhooks

GITHUB_WEBHOOK_SECRET=supersecret
WEBHOOK_API_SECRET=anothersecret

Variable names are case-insensitive and automatically mapped to the Pydantic fields (e.g., ENABLE_API_SERVER maps to enable_api_server).

Application Startup Sequence

When features.api_server_enabled evaluates to True, the run_application function in src/main.py (lines 310-320) creates an asynchronous task to start the server:


# src/main.py – launching the server

if features.api_server_enabled:
    from src.api.server import run_api_server
    api_task = asyncio.create_task(
        run_api_server(event_bus, config, storage.db_manager)
    )
    tasks.append(api_task)

This task runs in the same asyncio event loop as the Telegram bot, eliminating the need for separate processes or inter-process communication.

Webhook Processing Architecture

FastAPI Application Structure

The create_api_app function in src/api/server.py (lines 22-40) constructs the FastAPI instance with two primary endpoints:

  • Health check: Returns service status
  • Webhook receiver: /webhooks/{provider} route that accepts POST requests from external services

Event Handling Flow

When a webhook arrives, the receive_webhook endpoint (lines 41-115) performs the following:

  1. Signature validation: Verifies HMAC signatures for GitHub or Bearer tokens for generic webhooks using secrets from the configuration
  2. Deduplication: Checks SQLite via storage.db_manager to prevent processing duplicate delivery IDs
  3. Event publication: Creates a WebhookEvent object and publishes it to the EventBus defined in src/events/bus.py

The Telegram bot components subscribe to the EventBus and react to these events asynchronously.

Testing Your Configuration

After setting ENABLE_API_SERVER=true and starting the application, verify the server is listening:


# Run with debug logging to see startup confirmation

make run-debug

Look for the log entry:


INFO  API server enabled  port=9000

Test the webhook endpoint with cURL:

curl -X POST "http://localhost:9000/webhooks/custom" \
     -H "Authorization: Bearer anothersecret" \
     -H "Content-Type: application/json" \
     -d '{"event":"test","payload":{"msg":"hello"}}'

Expected response:

{
  "status": "accepted",
  "event_id": "a1b2c3d4-..."
}

Summary

  • Enable the server by setting ENABLE_API_SERVER=true in your environment or .env file, which maps to the enable_api_server field in src/config/settings.py.
  • Configure the port using API_SERVER_PORT (default 8080), defined in the same settings file and accessed via settings.api_server_port.
  • Startup logic in src/main.py checks features.api_server_enabled and spawns run_api_server as an asyncio task when enabled.
  • Architecture uses src/api/server.py for the FastAPI application, src/events/bus.py for internal event distribution, and SQLite for webhook deduplication.

Frequently Asked Questions

What port does the FastAPI webhook server use by default?

The default port is 8080, defined in src/config/settings.py via the api_server_port field. You can override this by setting the API_SERVER_PORT environment variable to any available TCP port.

Can I run the webhook server without the Telegram bot?

No. The FastAPI server is designed to run as a concurrent task within the same asyncio event loop as the Telegram bot, as implemented in src/main.py. It relies on the shared EventBus and database manager initialized by the main application, so it cannot operate as a standalone service.

How do I secure incoming webhook requests?

The server supports two authentication methods configured via environment variables. For GitHub webhooks, set GITHUB_WEBHOOK_SECRET to verify HMAC signatures. For generic webhooks, set WEBHOOK_API_SECRET and include it as a Bearer token in the Authorization header. Invalid signatures result in a 401 Unauthorized response.

Where are webhook events stored before processing?

Incoming webhooks are deduplicated using SQLite via the storage.db_manager passed to run_api_server. The receive_webhook endpoint in src/api/server.py checks delivery IDs against the database before publishing events to the EventBus, preventing duplicate processing of the same webhook payload.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →