Overview
The Pope Bot framework provides two Telegram endpoints:
- POST /api/telegram/register - Register your bot’s webhook URL
- POST /api/telegram/webhook - Receive incoming messages from Telegram
Register Webhook
Endpoint
POST /api/telegram/register
Registers your Telegram bot webhook with Telegram’s servers.
Authentication
Requires x-api-key header. See Authentication.
Request Body
Public HTTPS URL where Telegram will send updates (must be /api/telegram/webhook)
Example Request
curl -X POST https://your-domain.com/api/telegram/register \
-H "x-api-key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"bot_token": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
"webhook_url": "https://your-domain.com/api/telegram/webhook"
}'
Response
Success (200)
{
"success": true,
"result": {
"url": "https://your-domain.com/api/telegram/webhook",
"has_custom_certificate": false,
"pending_update_count": 0
}
}
Error Responses
Missing Parameters (400)
{
"error": "Missing bot_token or webhook_url"
}
Registration Failed (500)
{
"error": "Failed to register webhook"
}
Webhook Handler
Endpoint
POST /api/telegram/webhook
Receives incoming messages from Telegram.
Authentication
Public endpoint - Telegram authenticates using TELEGRAM_WEBHOOK_SECRET environment variable.
This endpoint does not require x-api-key header. Telegram verifies requests using the webhook secret.
How It Works
- Telegram sends message to
/api/telegram/webhook
- Server validates webhook secret
- Message normalized via
getTelegramAdapter().receive(request)
- Processes message asynchronously through AI layer
- Returns
{"ok": true} immediately (non-blocking)
- AI generates response and sends via Telegram API
async function handleTelegramWebhook(request) {
const botToken = getTelegramBotToken();
if (!botToken) return Response.json({ ok: true });
const adapter = getTelegramAdapter(botToken);
const normalized = await adapter.receive(request);
if (!normalized) return Response.json({ ok: true });
// Process message asynchronously (don't block webhook response)
processChannelMessage(adapter, normalized).catch((err) => {
console.error('Failed to process message:', err);
});
return Response.json({ ok: true });
}
Message Processing
- Acknowledge receipt to Telegram
- Start “typing” indicator
- Call
chat(threadId, text, attachments, metadata)
- Stream response back to user via Telegram
- Stop typing indicator
async function processChannelMessage(adapter, normalized) {
await adapter.acknowledge(normalized.metadata);
const stopIndicator = adapter.startProcessingIndicator(normalized.metadata);
try {
const response = await chat(
normalized.threadId,
normalized.text,
normalized.attachments,
{ userId: 'telegram', chatTitle: 'Telegram' }
);
await adapter.sendResponse(normalized.threadId, response, normalized.metadata);
} catch (err) {
console.error('Failed to process message with AI:', err);
await adapter
.sendResponse(
normalized.threadId,
'Sorry, I encountered an error processing your message.',
normalized.metadata
)
.catch(() => {});
} finally {
stopIndicator();
}
}
Environment Variables
Default bot token (can be overridden by /telegram/register)
Secret token for webhook authentication
Setup Example
1. Create Bot with BotFather
- Message @BotFather on Telegram
- Send
/newbot and follow prompts
- Save your bot token (looks like
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)
2. Set Environment Variables
TELEGRAM_BOT_TOKEN=your-bot-token-here
TELEGRAM_WEBHOOK_SECRET=random-secret-string
3. Register Webhook
curl -X POST https://your-domain.com/api/telegram/register \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"bot_token": "your-bot-token",
"webhook_url": "https://your-domain.com/api/telegram/webhook"
}'
4. Test Your Bot
Send a message to your bot on Telegram. It should respond using your configured LLM.
Channel Adapter
The Telegram integration uses a channel adapter pattern (lib/channels/telegram.js) to normalize messages into a common format:
{
threadId: string, // Telegram chat ID
text: string, // Message text
attachments: [], // Files, images, etc.
metadata: object // Telegram-specific data
}
This allows the AI layer (lib/ai/) to handle messages from any channel (Telegram, web chat, etc.) uniformly.