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:
- Signature validation: Verifies HMAC signatures for GitHub or Bearer tokens for generic webhooks using secrets from the configuration
- Deduplication: Checks SQLite via
storage.db_managerto prevent processing duplicate delivery IDs - Event publication: Creates a
WebhookEventobject and publishes it to theEventBusdefined insrc/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=truein your environment or.envfile, which maps to theenable_api_serverfield insrc/config/settings.py. - Configure the port using
API_SERVER_PORT(default8080), defined in the same settings file and accessed viasettings.api_server_port. - Startup logic in
src/main.pychecksfeatures.api_server_enabledand spawnsrun_api_serveras an asyncio task when enabled. - Architecture uses
src/api/server.pyfor the FastAPI application,src/events/bus.pyfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →