the three-layer api
puregram gives you three ways to call bot api methods. they're equivalent in capability — pick whichever reads best at the call site
// 1. raw — every method, schema-typed params, fully autogenerated
await tg.api.sendMessage({ chat_id: 100, text: 'hello' })
// 2. curated shortcut — positional args, chat first
await tg.send(100, 'hello')
// 3. per-kind shortcut — chat_id filled automatically from the update
tg.onMessage(message => message.send('hello'))layer 1 — tg.api.X(params) (raw)
the raw layer is fully autogenerated from the bot api schema. every method telegram documents is available here, typed with exact parameter shapes
// all params explicit — nothing is filled for you
await tg.api.sendMessage({
chat_id: 100,
text: 'hello',
parse_mode: 'HTML',
reply_parameters: { message_id: 42 }
})
// every method that telegram supports, including less common ones
await tg.api.banChatMember({ chat_id: -1001234567890, user_id: 777 })
await tg.api.createChatInviteLink({ chat_id: -1001234567890 })
await tg.api.answerCallbackQuery({ callback_query_id: '...', text: 'done' })when to use: when you need the full parameter surface, when you're calling a method that has no curated shortcut, or when the return value needs to be a raw TelegramX shape for interop
return type: raw bot-api interface (e.g. TelegramMessage, TelegramChatInviteLink)
layer 2 — tg.send(chat, text, params?) (curated)
the curated layer is a set of handcrafted and codegen'd shortcuts on the Telegram class that accept positional arguments and omit the fields they fill themselves
// positional: chat first, content second, extras optional
await tg.send(100, 'hello')
await tg.send(100, 'hello', { parse_mode: 'HTML' })
await tg.sendPhoto(100, MediaSource.path('./cat.png'), { caption: 'cute' })
await tg.sendDocument(100, MediaSource.url('https://example.com/file.pdf'))when to use: when you have the chat id in hand and want clean call sites without repeating chat_id: everywhere
return type: raw TelegramMessage (same as tg.api.sendMessage)
layer 3 — update.send(text, params?) (per-kind shortcut)
every message-bearing update class carries a set of codegen'd shortcuts that auto-fill the anchor — the chat_id (and other positional args) the method needs — from the update's own payload
tg.onMessage((message) => {
// chat_id is taken from message.raw.chat.id automatically
return message.send('got it')
})
tg.onCallbackQuery((callbackQuery) => {
// callback query answer — no chat_id needed
return callbackQuery.answer({ text: 'thanks' })
})when to use: inside an update handler when you're responding to the current update. this is the most common path
return type: raw TelegramMessage (same underlying tg.api.sendMessage call)
the per-kind shortcuts also include reply twins — message.reply(text) and message.replyWith<Media>(src) — that auto-fill reply_parameters.message_id so the response threads under the incoming message; see shortcuts for the full list
side-by-side: three ways to send the same message
const CHAT_ID = 100
const TEXT = 'hello there'
// layer 1 — explicit params object
await tg.api.sendMessage({
chat_id: CHAT_ID,
text: TEXT,
parse_mode: 'HTML'
})
// layer 2 — positional chat + text
await tg.send(CHAT_ID, TEXT, { parse_mode: 'HTML' })
// layer 3 — inside a handler, chat_id comes from the update
tg.onMessage(async (message) => {
await message.send(TEXT, { parse_mode: 'HTML' })
})all three send the same message. the only difference is how much you type
the escape hatch
for methods not yet in the codegen, or corefork-only beta methods, use tg.api.call:
// raw method name + params — no type-checking on the response
await tg.api.call('someBetaMethod', { foo: 'bar' })tg.api.call always throws on errors — there's no suppress option here
which layer should i use day to day?
layer 3 (update.send, update.delete, update.answer, ...) inside handlers. layer 2 (tg.send, tg.sendPhoto, ...) when you need to push a message outside of a handler (e.g. from a cron job). layer 1 (tg.api.X) when the curated shortcuts don't cover the parameter you need
see also
- shortcuts — the anchor concept and per-kind method list
- updates — the
Updateobjects passed to handlers - api reference overview — the generated method + object reference
- methods — full generated method list