Telegram

Connect to Telegram with support for groups, channels, inline keyboards, and a polling fallback for local development.

Install

pnpm add @chat-adapter/telegram

Quick start

The adapter auto-detects TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRET_TOKEN, and TELEGRAM_BOT_USERNAME from the environment.

lib/bot.ts
import { Chat } from "chat";
import { createTelegramAdapter } from "@chat-adapter/telegram";

const bot = new Chat({
  userName: "mybot",
  adapters: {
    telegram: createTelegramAdapter(),
  },
});

bot.onNewMention(async (thread, message) => {
  await thread.post(`You said: ${message.text}`);
});
app/api/webhooks/telegram/route.ts
import { bot } from "@/lib/bot";

export async function POST(request: Request): Promise<Response> {
  return bot.webhooks.telegram(request);
}

Configure your bot webhook in BotFather / via the Telegram API:

curl -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-domain.com/api/webhooks/telegram",
    "secret_token": "your-secret-token"
  }'

Configuration

Prop

Type

botToken is required — either via config or env var.

Authentication

Create a bot via BotFather:

  1. Send /newbot and follow the prompts.
  2. Copy the token to TELEGRAM_BOT_TOKEN.
  3. Optionally pick a username and copy it to TELEGRAM_BOT_USERNAME.

Advanced

Polling for local development

lib/bot.ts
import { Chat } from "chat";
import { createTelegramAdapter } from "@chat-adapter/telegram";
import { createMemoryState } from "@chat-adapter/state-memory";

const telegram = createTelegramAdapter({
  mode: "polling",
});

const bot = new Chat({
  userName: "mybot",
  adapters: { telegram },
  state: createMemoryState(),
});

Polling and webhooks are mutually exclusive in Telegram. mode: "polling" deletes the webhook by default before calling getUpdates.

Auto mode

mode: "auto" (the default) checks getWebhookInfo: if a webhook URL is set, it uses webhook mode; otherwise it falls back to polling on long-running runtimes. If getWebhookInfo fails, the adapter stays in webhook mode (safe fallback).

const telegram = createTelegramAdapter({ mode: "auto" });
void bot.initialize();
console.log(telegram.runtimeMode); // "webhook" | "polling"

Slash commands

Use bot.onSlashCommand to handle Telegram bot commands such as /status and /status@mybot. Commands addressed to another bot are ignored as slash commands and continue through the normal message path.

Markdown formatting

On Telegram Bot API 10.1 and newer, explicit { markdown } and { ast } messages use rich messages. Standard markdown gains native headings, lists, tables, task lists, formulas, details, and separate media blocks where supported by Telegram. Private chat streams use rich draft previews and persist the completed response as a rich message.

Plain strings, raw messages, cards, and media captions retain their existing lightweight message paths. Cards and captions use Telegram's MarkdownV2 parse mode with context-aware escaping. Older or custom Bot API servers automatically fall back to this existing path when rich message methods are unavailable.

Pass { raw: "..." } only if you need to ship a fully pre-escaped MarkdownV2 string.

Notes

  • Telegram does not expose full historical message APIs to bots. fetchMessages returns adapter-cached messages from the current process.
  • listThreads is not available for Telegram chats.
  • Telegram callback data is limited to 64 bytes — keep Button id/value payloads short.
  • Other rich card elements (images, select menus, radios) render as fallback text.

Feature support

Messaging

FeatureSupported
Post message
Edit message
Delete message
File uploadsSingle file
StreamingRich drafts / Post+Edit
Scheduled messages

Rich content

FeatureSupported
Card formatMarkdownV2 + inline keyboard
ButtonsInline keyboard
Link buttonsInline keyboard URLs
Select menus
TablesNative messages / ASCII cards
Fields
Images in cards
Modals

Conversations

FeatureSupported
Slash commands
Mentions
Add reactions
Remove reactions
Typing indicator
DMs
Ephemeral messages
User lookupSeen users
Parent subject
Native client
Custom API endpoint

Message history

FeatureSupported
Fetch messagesCached
Fetch single messageCached
Fetch thread info
Fetch channel messagesCached
List threads
Fetch channel info
Post channel message

On this page