Skip to main content
The Api class provides full access to the Telegram Bot API. All methods are available with convenient parameter handling and optional AbortSignal support for canceling requests.

Overview

The API client is available through:
  • bot.api - On the Bot instance
  • ctx.api - On the Context object (preferred inside middleware)
It provides:
  • Type-safe access to all Telegram Bot API methods
  • Automatic error handling with GrammyError and HttpError
  • Request transformation via the transformer system
  • Webhook reply optimization

Constructor

new Api(token: string, options?: ApiClientOptions, webhookReplyEnvelope?: WebhookReplyEnvelope)
token
string
required
Bot API token obtained from @BotFather
options
ApiClientOptions
Optional API client configuration
webhookReplyEnvelope
WebhookReplyEnvelope
Optional webhook reply envelope for optimized webhook responses

Properties

raw
RawApi
Provides raw access to all Telegram Bot API methods with 1:1 method signatures as documented on the official API reference.
// Raw API call
await bot.api.raw.sendMessage({
  chat_id: 123456,
  text: 'Hello!',
  parse_mode: 'Markdown'
})
config
object
Configuration namespace for advanced API operations.

Common Methods

All methods take an optional AbortSignal as the last parameter to cancel requests.

getMe

Returns basic information about the bot.
await api.getMe(signal?: AbortSignal): Promise<UserFromGetMe>
Example:
const botInfo = await bot.api.getMe()
console.log(`Bot username: @${botInfo.username}`)

sendMessage

Sends a text message.
await api.sendMessage(
  chat_id: number | string,
  text: string,
  other?: SendMessageOptions,
  signal?: AbortSignal
): Promise<Message>
chat_id
number | string
required
Unique identifier for the target chat or username of the target channel (in the format @channelusername)
text
string
required
Text of the message to send (1-4096 characters after entities parsing)
other
object
Optional parameters:
  • parse_mode: ‘Markdown’, ‘MarkdownV2’, or ‘HTML’
  • entities: List of special entities
  • reply_markup: Inline keyboard, custom keyboard, etc.
  • link_preview_options: Link preview settings
  • And more…
Example:
await bot.api.sendMessage(chatId, 'Hello, **world**!', {
  parse_mode: 'Markdown',
  reply_markup: {
    inline_keyboard: [[
      { text: 'Click me', callback_data: 'button_click' }
    ]]
  }
})

sendPhoto

Sends a photo.
await api.sendPhoto(
  chat_id: number | string,
  photo: InputFile | string,
  other?: SendPhotoOptions,
  signal?: AbortSignal
): Promise<Message>
photo
InputFile | string
required
Photo to send. Pass:
  • file_id as string (recommended for existing Telegram files)
  • HTTP URL as string
  • InputFile for uploading new files
Example:
import { InputFile } from 'grammy'

// Upload from file system
await bot.api.sendPhoto(
  chatId,
  new InputFile('/path/to/photo.jpg'),
  { caption: 'Check this out!' }
)

// From URL
await bot.api.sendPhoto(
  chatId,
  'https://example.com/photo.jpg'
)

// From file_id
await bot.api.sendPhoto(chatId, 'AgACAgIAAxkBAAI...')

sendDocument

Sends a document file.
await api.sendDocument(
  chat_id: number | string,
  document: InputFile | string,
  other?: SendDocumentOptions,
  signal?: AbortSignal
): Promise<Message>

sendAudio

Sends an audio file.
await api.sendAudio(
  chat_id: number | string,
  audio: InputFile | string,
  other?: SendAudioOptions,
  signal?: AbortSignal
): Promise<Message>

sendVideo

Sends a video file.
await api.sendVideo(
  chat_id: number | string,
  video: InputFile | string,
  other?: SendVideoOptions,
  signal?: AbortSignal
): Promise<Message>

sendAnimation

Sends an animation (GIF or H.264/MPEG-4 AVC video without sound).
await api.sendAnimation(
  chat_id: number | string,
  animation: InputFile | string,
  other?: SendAnimationOptions,
  signal?: AbortSignal
): Promise<Message>

sendVoice

Sends a voice message (OGG encoded with OPUS).
await api.sendVoice(
  chat_id: number | string,
  voice: InputFile | string,
  other?: SendVoiceOptions,
  signal?: AbortSignal
): Promise<Message>

sendVideoNote

Sends a video note (round video message).
await api.sendVideoNote(
  chat_id: number | string,
  video_note: InputFile | string,
  other?: SendVideoNoteOptions,
  signal?: AbortSignal
): Promise<Message>

sendMediaGroup

Sends a group of photos, videos, documents or audios as an album.
await api.sendMediaGroup(
  chat_id: number | string,
  media: InputMedia[],
  other?: SendMediaGroupOptions,
  signal?: AbortSignal
): Promise<Message[]>
Example:
await bot.api.sendMediaGroup(chatId, [
  {
    type: 'photo',
    media: 'https://example.com/photo1.jpg',
    caption: 'Photo 1'
  },
  {
    type: 'photo',
    media: new InputFile('/path/to/photo2.jpg'),
    caption: 'Photo 2'
  }
])

sendLocation

Sends a location point on the map.
await api.sendLocation(
  chat_id: number | string,
  latitude: number,
  longitude: number,
  other?: SendLocationOptions,
  signal?: AbortSignal
): Promise<Message>

sendVenue

Sends information about a venue.
await api.sendVenue(
  chat_id: number | string,
  latitude: number,
  longitude: number,
  title: string,
  address: string,
  other?: SendVenueOptions,
  signal?: AbortSignal
): Promise<Message>

sendContact

Sends a phone contact.
await api.sendContact(
  chat_id: number | string,
  phone_number: string,
  first_name: string,
  other?: SendContactOptions,
  signal?: AbortSignal
): Promise<Message>

sendPoll

Sends a native poll.
await api.sendPoll(
  chat_id: number | string,
  question: string,
  options: string[] | InputPollOption[],
  other?: SendPollOptions,
  signal?: AbortSignal
): Promise<Message>
Example:
await bot.api.sendPoll(
  chatId,
  'What is your favorite color?',
  ['Red', 'Blue', 'Green'],
  {
    is_anonymous: false,
    allows_multiple_answers: true
  }
)

sendDice

Sends an animated emoji with a random value.
await api.sendDice(
  chat_id: number | string,
  emoji: '🎲' | '🎯' | '🏀' | '⚽' | '🎳' | '🎰',
  other?: SendDiceOptions,
  signal?: AbortSignal
): Promise<Message>

Message Management

editMessageText

Edits text and game messages.
// Regular message
await api.editMessageText(
  chat_id: number | string,
  message_id: number,
  text: string,
  other?: EditMessageTextOptions,
  signal?: AbortSignal
): Promise<Message | true>

// Inline message
await api.editMessageTextInline(
  inline_message_id: string,
  text: string,
  other?: EditMessageTextOptions,
  signal?: AbortSignal
): Promise<true>

editMessageReplyMarkup

Edits only the reply markup of messages.
await api.editMessageReplyMarkup(
  chat_id: number | string,
  message_id: number,
  other?: EditMessageReplyMarkupOptions,
  signal?: AbortSignal
): Promise<Message | true>

deleteMessage

Deletes a message.
await api.deleteMessage(
  chat_id: number | string,
  message_id: number,
  signal?: AbortSignal
): Promise<true>

deleteMessages

Deletes multiple messages simultaneously.
await api.deleteMessages(
  chat_id: number | string,
  message_ids: number[],
  signal?: AbortSignal
): Promise<true>

forwardMessage

Forwards a message.
await api.forwardMessage(
  chat_id: number | string,
  from_chat_id: number | string,
  message_id: number,
  other?: ForwardMessageOptions,
  signal?: AbortSignal
): Promise<Message>

copyMessage

Copies a message (without the forward header).
await api.copyMessage(
  chat_id: number | string,
  from_chat_id: number | string,
  message_id: number,
  other?: CopyMessageOptions,
  signal?: AbortSignal
): Promise<MessageId>

Chat Management

getChat

Gets up-to-date information about the chat.
await api.getChat(
  chat_id: number | string,
  signal?: AbortSignal
): Promise<Chat>

getChatAdministrators

Gets a list of administrators in a chat.
await api.getChatAdministrators(
  chat_id: number | string,
  signal?: AbortSignal
): Promise<ChatMember[]>

getChatMemberCount

Gets the number of members in a chat.
await api.getChatMemberCount(
  chat_id: number | string,
  signal?: AbortSignal
): Promise<number>

getChatMember

Gets information about a member of a chat.
await api.getChatMember(
  chat_id: number | string,
  user_id: number,
  signal?: AbortSignal
): Promise<ChatMember>

banChatMember

Bans a user in a group, supergroup or channel.
await api.banChatMember(
  chat_id: number | string,
  user_id: number,
  other?: BanChatMemberOptions,
  signal?: AbortSignal
): Promise<true>

unbanChatMember

Unbans a previously banned user.
await api.unbanChatMember(
  chat_id: number | string,
  user_id: number,
  other?: UnbanChatMemberOptions,
  signal?: AbortSignal
): Promise<true>

restrictChatMember

Restricts a user in a supergroup.
await api.restrictChatMember(
  chat_id: number | string,
  user_id: number,
  permissions: ChatPermissions,
  other?: RestrictChatMemberOptions,
  signal?: AbortSignal
): Promise<true>

promoteChatMember

Promotes or demotes a user in a supergroup or channel.
await api.promoteChatMember(
  chat_id: number | string,
  user_id: number,
  other?: PromoteChatMemberOptions,
  signal?: AbortSignal
): Promise<true>

leaveChat

Leaves a group, supergroup or channel.
await api.leaveChat(
  chat_id: number | string,
  signal?: AbortSignal
): Promise<true>

Callback Queries

answerCallbackQuery

Answers a callback query from an inline button.
await api.answerCallbackQuery(
  callback_query_id: string,
  other?: AnswerCallbackQueryOptions,
  signal?: AbortSignal
): Promise<true>
Example:
await bot.api.answerCallbackQuery(queryId, {
  text: 'Button clicked!',
  show_alert: true
})

Inline Queries

answerInlineQuery

Answers an inline query.
await api.answerInlineQuery(
  inline_query_id: string,
  results: InlineQueryResult[],
  other?: AnswerInlineQueryOptions,
  signal?: AbortSignal
): Promise<true>
Example:
await bot.api.answerInlineQuery(queryId, [
  {
    type: 'article',
    id: '1',
    title: 'Result 1',
    input_message_content: {
      message_text: 'Content 1'
    }
  }
], {
  cache_time: 300
})

Bot Information

setMyCommands

Sets the list of the bot’s commands.
await api.setMyCommands(
  commands: BotCommand[],
  other?: SetMyCommandsOptions,
  signal?: AbortSignal
): Promise<true>
Example:
await bot.api.setMyCommands([
  { command: 'start', description: 'Start the bot' },
  { command: 'help', description: 'Show help' },
  { command: 'settings', description: 'Open settings' }
])

getMyCommands

Gets the current list of the bot’s commands.
await api.getMyCommands(
  other?: GetMyCommandsOptions,
  signal?: AbortSignal
): Promise<BotCommand[]>

setMyName

Changes the bot’s name.
await api.setMyName(
  name: string,
  other?: SetMyNameOptions,
  signal?: AbortSignal
): Promise<true>

setMyDescription

Changes the bot’s description.
await api.setMyDescription(
  description: string,
  other?: SetMyDescriptionOptions,
  signal?: AbortSignal
): Promise<true>

Webhooks

setWebhook

Sets a webhook URL to receive updates.
await api.setWebhook(
  url: string,
  other?: SetWebhookOptions,
  signal?: AbortSignal
): Promise<true>

deleteWebhook

Removes webhook integration.
await api.deleteWebhook(
  other?: DeleteWebhookOptions,
  signal?: AbortSignal
): Promise<true>

getWebhookInfo

Gets current webhook status.
await api.getWebhookInfo(
  signal?: AbortSignal
): Promise<WebhookInfo>

Updates

getUpdates

Receives incoming updates using long polling.
await api.getUpdates(
  other?: GetUpdatesOptions,
  signal?: AbortSignal
): Promise<Update[]>
Note: This method should not be called manually when using bot.start(). It’s used internally by grammY.

Transformers

Transformers allow you to modify API calls before they are sent to Telegram.
bot.api.config.use(async (prev, method, payload, signal) => {
  // Log all API calls
  console.log(`Calling ${method}`)
  
  // Modify payload
  if (method === 'sendMessage') {
    payload.parse_mode = 'Markdown'
  }
  
  // Call the API
  const result = await prev(method, payload, signal)
  
  // Log result
  console.log(`${method} completed`)
  
  return result
})
Common use cases:
  • Rate limiting
  • Logging
  • Default parameters
  • Request retrying
  • Caching

Error Handling

The API client throws two types of errors:

GrammyError

Thrown when the Telegram API returns an error response.
import { GrammyError } from 'grammy'

try {
  await bot.api.sendMessage(chatId, 'Hello')
} catch (error) {
  if (error instanceof GrammyError) {
    console.error('API Error:', error.error_code, error.description)
    // error.method - The failed method
    // error.parameters - Extra parameters (e.g., retry_after)
  }
}

HttpError

Thrown when the HTTP request fails (network error, timeout, etc.).
import { HttpError } from 'grammy'

try {
  await bot.api.getMe()
} catch (error) {
  if (error instanceof HttpError) {
    console.error('Network error:', error.message)
  }
}

Complete Example

import { Bot, InputFile, GrammyError } from 'grammy'

const bot = new Bot('YOUR_BOT_TOKEN', {
  client: {
    apiRoot: 'https://api.telegram.org',
    timeoutSeconds: 60
  }
})

// Use transformers for logging
bot.api.config.use(async (prev, method, payload) => {
  console.log(`API call: ${method}`)
  return await prev(method, payload)
})

bot.command('start', async (ctx) => {
  // Send text with keyboard
  await ctx.api.sendMessage(ctx.chatId!, 'Welcome!', {
    reply_markup: {
      inline_keyboard: [[
        { text: 'Button', callback_data: 'btn' }
      ]]
    }
  })
  
  // Send photo
  await ctx.api.sendPhoto(
    ctx.chatId!,
    new InputFile('/path/to/image.jpg'),
    { caption: 'Check this out!' }
  )
  
  // Get chat info
  const chat = await ctx.api.getChat(ctx.chatId!)
  console.log('Chat title:', chat.title)
})

bot.catch((err) => {
  const error = err.error
  if (error instanceof GrammyError) {
    console.error('Telegram error:', error.description)
  } else {
    console.error('Unknown error:', error)
  }
})

bot.start()

See Also

Build docs developers (and LLMs) love