Skip to main content

Triggers

A trigger decides when a flow runs. Every flow declares exactly one. This page is an overview of all trigger kinds with a quick example each; for the precise argument and filter reference, see Statement Reference β†’ Triggers.

Command​

Runs when a user sends a slash command.

flow help on command "/help" {
send.text("Here's how I work…")
}

Message (with filters)​

Runs on incoming messages. An optional filter restricts it to a content type.

// Any text message
flow echo on message [text] {
send.text(`You said: ${message.text}`)
}

// Only photos
flow on_photo on message [photo] {
send.text("Nice photo!")
}

Filters: text, photo, video, audio, voice, document, sticker, animation, contact, location, poll, dice, any.

Callback (and prefix)​

Runs when an inline keyboard button is tapped. The string matches the button's callback_data. A trigger ending in : is a prefix match β€” it catches any payload starting with that prefix.

flow open_menu on callback "menu" {
send.text("Main menu")
}

// Prefix: matches "buy:coffee", "buy:tea", …
flow buy on callback "buy:" {
set { flow.item = str.split(callback.data, ":")[1] }
send.text(`You picked ${flow.item}`)
}

See Dynamic keyboards for prefix routing patterns.

Schedule (cron)​

Runs on a cron schedule. The flow has no chat in scope, so send to an explicit chat_id.

// Every day at 09:00
flow daily on schedule "0 9 * * *" {
send.text("Good morning! β˜€οΈ", chat_id: shared.group_chat_id)
}

Webhook​

Runs when an external system sends an HTTP request to your bot's webhook URL β€” used for payment confirmations, third-party callbacks, and integrations.

flow ping on webhook "health" {
respond.text("ok")
}

Webhooks support signature verification, typed bodies, and custom responses. See Statement Reference β†’ Webhooks and Payments & webhooks.

Group events​

For bots in groups and channels, these fire on membership changes:

flow greet on join {
set { flow.name = member.new_chat_member.user.first_name }
send.text(`πŸ‘‹ Welcome, ${flow.name}!`)
}

flow farewell on leave {
send.text("Someone left the group.")
}

flow review on join_request {
send.text(`Join request from ${request.from.first_name}`)
}

flow added on bot_added {
send.text("Thanks for adding me! Admin: run /setup here.")
}

flow removed on bot_removed { /* cleanup */ }

There's also a filtered member trigger for fine-grained membership events:

flow on_ban on member [banned] {
set { flow.name = member.new_chat_member.user.first_name }
send.text(`πŸ”¨ ${flow.name} was banned.`)
}

member filters: joined, left, banned, unbanned, promoted, demoted, restricted.

See Groups & admin and Groups & moderation for the full toolkit.

Payments (Telegram Stars)​

A Stars purchase fires two triggers: on pre_checkout validates the order (the runtime auto-approves so the charge proceeds), then on successful_payment delivers the goods.

flow precheck on pre_checkout {
// Validate; runtime auto-approves the pre_checkout_query.
debug.log(`Order: ${pre_checkout.invoice_payload} for ⭐${pre_checkout.total_amount}`)
}

flow paid on successful_payment {
send.text(`βœ… Paid ⭐${payment.total_amount} β€” unlocked!`)
}

Read pre_checkout.* (invoice_payload, total_amount, currency, id) and payment.* (total_amount, invoice_payload, telegram_payment_charge_id). Start an invoice with send.invoice.

Telegram Business​

For bots connected to a Telegram Business account. send.* inside these flows replies as the account owner.

flow concierge on business_message {
send.text(`Thanks! You said: ${business.text}`)
}

Triggers: on business_connection, on business_message, on edited_business_message, on deleted_business_messages. Read business.* (connection_id, text, from, can_reply, is_enabled, user).

Mini Apps, reactions, and inline mode​

// Data sent from a Mini App (authenticate first)
flow on_webapp on web_app_data {
when crypto.verifyInitData(web_app.data, global.bot_token) {
send.text("Verified Mini App request.")
}
}

// A user adds/removes an emoji reaction
flow on_react on reaction {
when reaction.added { send.text(`Reacted: ${reaction.emoji}`) }
}

// Inline mode: @yourbot <query>
flow inline on inline_query {
answer_inline(inline.id, [{ id: "1", title: "Result", text: "Hi" }])
}

Read web_app.* (data, button_text), reaction.* (emoji, added, message_id, user), and inline.* (id, query, offset, from).

Trigger reference​

TriggerFires when…
on command "/x"A user sends /x
on message [filter]A message of that content type arrives
on callback "data"A matching inline button is tapped (: = prefix)
on schedule "cron"The cron expression matches
on webhook("name", …)An HTTP request hits the webhook URL
on join / on leaveA user joins / leaves a group
on join_requestA user requests to join
on bot_added / on bot_removedThe bot is added to / removed from a chat
on member [filter]A membership sub-event occurs
on pre_checkoutA Stars purchase reaches pre-checkout
on successful_paymentA Stars payment completes
on business_connectionA Business account connects/disconnects the bot
on business_messageA customer DMs a connected Business account
on edited_business_messageA message in a connected Business chat is edited
on deleted_business_messagesMessages in a connected Business chat are deleted
on web_app_dataA Mini App sends data to the bot
on reactionA user adds/removes an emoji reaction
on inline_queryA user types @yourbot <query>

Next​