Telegram client and transport
Use the validated Bot API client when an application needs Bot API operations without the Channel abstraction, and the parse/normalize helpers when integrating a custom receive transport. See @anvia/telegram for standard setup.
Use the validated client directly
import { createTelegramBotApiClient, TelegramApiError } from '@anvia/telegram'
const api = createTelegramBotApiClient({ token })
try {
const bot = await api.getMe()
console.log(bot.username)
} catch (error) {
if (error instanceof TelegramApiError) {
console.error(error.method, error.errorCode, error.retryAfterSeconds)
}
}The client exposes getMe, getUpdates, sendMessage, sendAttachment, editMessageText, answerCallbackQuery, deleteMessage, sendChatAction, setMessageReaction, and downloadFile. Options beyond the token:
baseUrltargets a custom (usually self-hosted) Bot API server; any HTTPS URL is accepted, while plain HTTP works only forlocalhost,127.0.0.1, or::1.fetchreplaces the Fetch implementation for proxies and test doubles.maximumAttachmentBytescaps upload and download sizes (20 MiB by default).
Failures surface as TelegramApiError carrying method, the Bot API errorCode when present, and retryAfterSeconds for rate limits. Request failures never embed the request URL, so the token cannot leak into error messages.
Five calls retry on HTTP 429 (up to three attempts, honoring Telegram's retry_after hint, abort-aware): sendMessage, URL-based sendAttachment, editMessageText, deleteMessage, and setMessageReaction. answerCallbackQuery, sendChatAction, getMe, getUpdates, downloads, and multipart (base64) uploads never retry. For steadier pacing on top of retries, wrap the adapter with createRateLimitedChannel().
Integrate a custom receive transport
At an untrusted HTTP boundary, validate first, then normalize:
import { normalizeTelegramUpdate, parseTelegramUpdate } from '@anvia/telegram'
const parsed = parseTelegramUpdate(payload)
const events = normalizeTelegramUpdate(parsed, bot)parseTelegramUpdate() throws a TypeError for a missing or non-integer update_id or a malformed recognized field, and it ignores unrecognized update kinds. bot is the TelegramUser from getMe(); normalization needs it for the event accountId and mentionedBot detection. Do not normalize raw unknown JSON without parsing it first.
Shutdown
await channel.stop()Polling shutdown aborts an in-flight getUpdates and drains the loop; webhook shutdown rejects new deliveries and waits for active ones.
Continue with
- Telegram polling and webhooks — the built-in receive modes.
- Receive Telegram events — the normalized events.