Back to blog

Make Telegram bot buttons safe: callbacks, authorization, and stale state

Define fast callback acknowledgement, server-side authorization, idempotency, expiration, and failure feedback for confirmation and approval buttons.

Published October 13, 2026

Inline buttons work well for confirming registrations, approving requests, changing settings, and paging through results because a click does not post an ordinary text message to the chat. But a button-shaped interface does not guarantee one-time execution, and it does not prove that the person clicking is allowed to perform the action. Messages can remain accessible for a long time, buttons can be pressed repeatedly, and a network failure can happen after a database write succeeds.

Telegram's button documentation says callback buttons send data to the bot and the bot must answer the query quickly, even when no visible notification is needed. grammY's keyboard guide also recommends a fallback for unknown callbacks; otherwise, some clients may keep showing a loading animation. The business action still needs fresh server-side validation.

Separate acknowledgement from completion

A button handler has at least two different outcomes:

  1. Interaction acknowledgement tells Telegram that the click arrived and stops the client spinner.
  2. Business completion tells the user whether approval, capacity reservation, or a settings update actually succeeded.

Acknowledge promptly. The business operation may be slower or fail. Do not leave the user with an endless spinner, but do not display “completed” before the authoritative write succeeds. For longer work, show a processing message and then edit the original message or send a clear final result.

Treat callback data as a locator, not authority

The data attached to a button comes back to the bot. It is useful for a compact, verifiable action type and record identifier, such as “approve:request_123.” It should not carry the complete order, trusted price, authorization decision, or long user-supplied text.

When the callback arrives, load current data from trusted storage and verify that:

  • the action type is allowlisted;
  • the record exists and is still actionable;
  • the current sender is an authorized user or administrator;
  • the chat, message, and record belong together;
  • price, capacity, and role values come from current server-side data;
  • the button version or expiration time is still valid.

aiogram's Callback Data Factory documentation demonstrates structured prefixes, packing, parsing, and filters. A bot does not need aiogram to adopt the same principle: define one format and reject values that do not match it.

Make repeated clicks a normal case

A double tap, a network retry, or reopening an old message can deliver the same intent more than once. Side-effecting actions need business idempotency keys, for example:

  • approval: request ID plus action;
  • registration: draft ID plus confirmation version;
  • reward claim: user ID plus campaign ID;
  • settings: setting ID plus the target value, not “toggle the current value.”

“Set enabled” remains enabled when repeated. “Invert the current value” twice silently returns to the starting state. For charges, rewards, or record creation, check for an existing result and change state atomically. Webhook deduplication helps with repeated updates, but it does not replace business idempotency for buttons.

Give stale buttons a defined outcome

The message containing a button may outlive the business state. After completion, edit the keyboard into a disabled state, remove it, or change the message to “Approved by Alice.” If another administrator already acted or the record expired, return “already processed” or “expired” instead of failing silently.

Define these branches too:

  • the original message was deleted or the bot can no longer edit it;
  • the record exists but the clicker's permission was revoked;
  • two administrators choose opposite actions concurrently;
  • the callback is acknowledged but an external service ends in an unknown state;
  • a release changes callback format while old buttons remain in chats.

Irreversible actions may use a second confirmation. That second button still needs authorization and idempotency; the confirmation screen is not a security boundary.

A requirement template you can adapt

Build a group approval bot. Each request message has Approve and Reject buttons. A click promptly ends Telegram's loading state, then verifies that the sender is currently an authorized administrator, the request is still pending, and the button belongs to that request. Approve or Reject may succeed only once. If administrators act concurrently, the first valid decision wins and later clicks show the final state. Edit the original message after completion, remove actionable buttons, and display the actor and time. Unknown, old-format, expired, or unauthorized callbacks explain the issue without changing data.

For payments, rewards, deletion, or external APIs, also specify compensation, manual review, and unknown-result handling.

Acceptance checklist

  • One click clears the client loading state promptly.
  • Two rapid clicks produce one business side effect.
  • Two administrators choosing opposite actions produce one final state.
  • An ordinary member cannot execute an administrator action.
  • Forwarded, old, or expired buttons cannot change the current record.
  • Unknown and legacy callback formats receive a clear response.
  • A successful write plus a failed message edit does not repeat or roll back the action.
  • A failed write never leaves the button looking successful.
  • Completed buttons are removed, disabled, or replaced by final status.

How this relates to BotFatherV2

BotFatherV2 creates and modifies Telegram Serverless bots from a natural-language conversation. Defining the actor, valid state, duplicate-click behavior, and failure feedback turns “add two buttons” into testable business rules.

AI-assisted development does not automatically give the deployed bot an AI agent, arbitrary external APIs, or arbitrary npm packages. Implementation remains constrained by Telegram Serverless and the documented fixed SDK surface. Payments and external services require separate checks for support, credentials, and costs. BotFatherV2 is independent and is not affiliated with Telegram's official BotFather.

Sources

Related articles

Continue with articles that share the same product tags.

Design Telegram bot broadcasts: subscriptions, rate limits, and retries

Turn notification broadcasts into pausable, resumable jobs with consent, 429 handling, bounded retries, unsubscribe state, failure classes, and progress.

Design multi-step Telegram bots: state, cancellation, and timeouts

Turn registration, intake, and support bots into recoverable flows with explicit state, validation, cancellation, timeout, concurrency, and release rules.

Telegram bot deep links: start parameters, group installation, and attribution

Design testable Telegram bot onboarding with start and startgroup links, the 64-character limit, safe attribution, permissions, and replay handling.

Designing long-running Telegram bots: streaming replies, stop controls, and private topics

Turn streaming drafts, stop controls, and private-chat topics into testable requirements for Telegram search, report, and AI workflows.

Prevent duplicate processing in Telegram Serverless bots: webhook and idempotency checklist

Turn Telegram webhook retries and update_id behavior into testable requirements that prevent duplicate writes, rewards, orders, and stale updates.

Design Telegram bot interactions: commands, buttons, or natural language

Choose commands, reply keyboards, inline buttons, and text input by task, then turn those choices into testable Telegram bot requirements.