Buttons

Button Types

The builder features two fundamentally different types of buttons:

  • Inline buttons — attached to a specific message and remain on the screen.
  • Keyboard buttons (Reply) — appear at the bottom of the screen below the input field, acting like a quick-reply panel.

Both types can be added as options to Text, Image, Video, Audio, and Document blocks.

Inline Buttons

Inline buttons are positioned directly below the message text. Pressing a button takes the user to another node or triggers an action.

Button Actions

Action Type Description
Go to node Navigates the user to a specific scenario node
Go to command Navigates based on a text command (e.g., /menu)
URL Opens an external link
Select value (Options) Sets a variable value without navigating to a node
Delete current message Deletes the message containing the button upon pressing, without navigating to another node
💳 Payment link Generates a payment link via an external payment provider (Tinkoff, YooKassa, Stripe, etc.)
🔄 Subscription (recurring) Sets up an auto-renewing subscription via recurring payments
❌ Cancel subscription Cancels the user's active subscription
Edit via input (ForceReply) Requests a new value from the user via ForceReply and saves it to user_config or the user record

Button Layout

Buttons can be arranged in a row (multiple buttons on one line) or in a column (each on its own line). Use the arrows to the right of the buttons to change their order or move them to a different row.

Inline Keyboard Settings

Option Description
Delete message after selection The message containing the buttons is completely removed from the chat immediately after any button is pressed
Delete buttons after selection The buttons are removed from the message after a press, but the message itself remains in the chat

"Delete message" and "Delete buttons" are mutually exclusive; "Delete message" takes priority. Neither option is compatible with "Update message after selection."

Keyboard Buttons (Reply)

Keyboard buttons appear below the user's input field and function like text messages: pressing one sends the button's text to the bot, and the bot responds as if it were a command.

Use Reply buttons for menu navigation when a "persistent" list of actions is convenient.

Reply Keyboard Settings

Option Description
Show once Telegram automatically hides the keyboard after the user presses any button
Remove keyboard After a button is pressed, the bot sends the next message with the remove_keyboard: true flag, permanently removing the keyboard from the user's view. If a new Reply keyboard is specified in the next command, it replaces the old one without a removal step
Optimize size Makes the buttons more compact

"Show once" and "Remove keyboard" are mutually exclusive—only one of them can be enabled.

"Select Value" Button (Options)

Allows you to offer the user a choice from several options without creating separate nodes for each one. When the button is pressed, the specified value is saved to a variable, and the bot remains in the current node.

Example: "Male", "Female", and "Prefer not to say" buttons—each saves its specific value to the gender variable. After the response, the bot continues the scenario.

Dynamic Buttons

If you need to display a list of buttons based on data (e.g., a product list or search results), use dynamic buttons. The bot automatically generates one button for each element in the array variable.

Dynamic Button Settings

Field Description
Array variable The name of the variable containing the list of elements
Button text template The label for each button, e.g., {{item.name}}
Save selection to variable (optional) Saves the entire object of the selected list item to a variable
Target node The node to navigate to upon pressing
Delete message after selection The message containing the buttons will be deleted from the chat after a press
Delete buttons after selection Buttons are removed from the message after being pressed, but the message itself remains

When a user presses one of the buttons, the corresponding element's payload is saved to the specified variable, and the bot proceeds to the target node.

Bot Command Menu

In addition to buttons within messages, the bot features a global command menu—a list that opens when the user types "/" in the input field or taps the "Menu" button next to it.

Commands are configured automatically upon publication: any node with a non-empty "Command" field is included in this menu.

Tips

  • Avoid cluttering messages with too many buttons; 3–5 options on screen are sufficient for easy selection.
  • Use dynamic buttons for lists that change based on user data.
  • Inline buttons are preferable to Reply buttons for multi-step scenarios, as they do not take up space on the keyboard.

Active Button Highlighting

Allows you to visually mark the "active" option among several buttons using a symbol (✅, ✔️, ☑️). If the condition is met, the symbol is added to the beginning of the button text.

Setup: Enable "Button Highlighting" in the button inspector → specify the variable, comparison operator, and value. Select the symbol.

Example: "Light" and "Dark" buttons with {{user_config.theme}} = light / dark. When a button is pressed and the theme is saved to user_config, the keyboard updates, and the active theme is marked with ✅.

Highlighting for Dynamic Buttons

In dynamic button mode, there is a specific "Active Button Highlighting" setting: a single condition applies to all buttons in the list. You can use {{item.field}} within the condition to reference data from the current item.

Example: {{item.id}} = {{user_config.selected_id}} — marks the item selected by the user.

Conditional Button Display

Allows you to show or hide a button based on a variable's value. If at least one condition is not met (using "AND" logic) or none are met (using "OR" logic), the button is not rendered on the keyboard.

Setup: In the button inspector, open the "Conditional Display" section → add one or more rules → for each rule, specify the variable, operator, and value → select the combination logic (AND / OR).

Supported Operators:

Operator Description
Equals / Not equals Exact string match (case-insensitive)
Contains / Does not contain Substring within the variable value
Greater than (>) / Less than (<) Numeric comparison
>= / <= Numeric comparison (inclusive)
String length (>) Number of characters in the variable value exceeds the specified number
String length (<) The number of characters in the variable's value is less than the specified number
Exists / Does not exist The variable is defined (resolves) or not

String length example: show the "Shorten" button only if {{user_input}} is longer than 100 characters — use the "String length (>)" operator with a value of 100. If the variable is empty or does not exist, the length is considered to be 0.

Button color (dynamic layout)

Allows you to assign a specific color to each button based on the item's data. Enable "Button color" and specify a template that returns one of four values ​​for each item:

Value Button color
primary Blue (primary)
success Green
danger Red
secondary Gray

Example: enter {{item.color}} in the "Button color" field, and in the data for each array item, define a color field with the value danger, success, primary, or secondary.

If the field is missing or its value is not one of the valid options, the button is displayed without a color indicator.

Passing variables during transition (Pass Variables)

When using the "Go to node", "Call sub-scenario", or "Return to main scenario" button, you can pass a set of variables; these will be available in the scenario as standard variables.

Configuration: enable "Pass variables" → add key/value pairs. The value supports {{variable}} placeholders.

Use case example: multiple buttons lead to the same handler node, but each passes a specific action code ({{action}} = buy / sell / info). Example involving a sub-scenario: the "Buy Product" button passes {{product_id}} when entering the payment sub-scenario, while the return button passes {{payment_status}} back to the main scenario.

Update Original Message (Auto-refresh)

A setting at the node level (section "Actions" → "Update original message"). If enabled, after the command executes, the bot automatically updates the keyboard of the message from which the transition originated.

This allows for the implementation of "radio buttons" without resending the message: press a button, the checkmark moves, but the message itself remains unchanged.

Note: Incompatible with "Delete previous message" and "Next step."

Edit via Input (ForceReply)

A button action type that allows you to request a new text value from the user and save it to their profile or records.

Button configuration:

Field Description
Prompt text The bot's message requesting input
Input field hint Placeholder in the Telegram input field (supports {{user_config.key}})
Save key Key name in user_config or name in user_logs
Data source user_config (config) or user_logs (records)
Update command The node whose keyboard will update after saving. If not specified, the original node updates

After the user enters a value, the bot deletes both messages (request + response) and updates the original node's keyboard.

Additional buttons in dynamic layout

Buttons added below the generated dynamic list (e.g., "Back," "Refresh"). They now function as full-fledged inline buttons:

  • Support all action types (navigation, URL, message deletion, ForceReply, etc.)
  • Can be arranged in multiple rows with multiple buttons per row
  • Support highlighting

"Subscription" Button (recurring payments)

Available on paid plans.

Allows users to sign up for a subscription with automatic periodic charges via recurring payments. The user links their card once, and subsequent charges occur automatically.

Configuration

Click the button in the editor → select the Subscription (recurring) action → click Configure subscription.

Key parameters:

Field Description
Provider External payment provider supporting recurring payments (managed in Payment settings)
Amount Periodic charge amount. Supports variables: {{order_sum}}
Currency RUB, USD, EUR, KZT, UAH
Period (days) Billing interval: 1 = daily, 7 = weekly, 30 = monthly
Max. charge attempts Number of retries upon failure (1–5). Available only for providers with passive charging (T-Bank)
Payment description Text displayed on the payment form. Supports variables
Additional parameters Custom key/value pairs; passed to the provider and accessible via {{sub.payload.key}} variables

Subscription Lifecycle Events

Each event triggers the specified node and passes subscription variables to it.

Event Description
First payment successful Initial payment confirmed; subscription activated
First payment failed Initial payment declined
Successful renewal Automatic charge for the next period succeeded
Subscription cancelled User cancelled the subscription
Renewal error (attempt limit) Automatic charge failed and the attempt limit was reached

Subscription Variables

By default, variables are available with the prefixes payment.* (initial payment) and sub.* (subscription data). These prefixes can be changed in the button settings.

Initial payment variables (payment.*):

Variable Value
{{payment.amount}} Initial payment amount
{{payment.currency}} Currency
{{payment.status}} Payment status

Subscription variables (sub.*):

Variable Value
{{sub.id}} Subscription ID
{{sub.status}} pending / active / past_due / failed / cancelled
{{sub.amount}} Recurring charge amount
{{sub.currency}} Currency
{{sub.period_days}} Period in days
{{sub.card_mask}} Card mask (4242****4242)
{{sub.card_type}} Card type (VISA, Mastercard...)
{{sub.charge_attempts}} Number of failed attempts
{{sub.max_attempts}} Max. number of attempts
{{sub.next_charge_at}} Next charge date
{{sub.last_charged_at}} Last charge date
{{sub.payload.key}} Additional parameter from the Additional parameters block

Canceling a subscription

Use the Cancel subscription action button and specify the subscription ID (e.g., {{sub.id}}). Once canceled, the "Subscription canceled" node will trigger, if configured.

Scenario example

  1. The bot sends a message "Pro Subscription — 299 ₽/month" with a Subscribe button.
  2. The user clicks the button → proceeds to the payment provider's page and links their card.
  3. The "First payment successful" node triggers: the bot sends a message "Access granted!" containing the variables {{sub.card_mask}} and {{sub.next_charge_at}}.
  4. Every 30 days, the system automatically charges the payment → the "Successful renewal" node triggers.
  5. If the card is blocked, the system retries after 24 hours. Once the limit is reached, the "Renewal error" node triggers.

Requirements

  • This feature is available only on paid plans.
  • A payment provider must be connected in the "Payments → External providers" section with the "Subscriptions" option enabled.

Additional buttons in the dynamic layout

Buttons added below the generated dynamic list (e.g., "Back", "Refresh"). They are now fully functional inline buttons:

  • They support all types of actions (navigation, URL, message deletion, ForceReply, etc.)
  • They can be arranged in multiple rows, with multiple buttons per row
  • They support highlighting