· 7 min read
Tutorial: Using Telegram Bot API 7.1’s New Paid Messages for High-Value Bot Interactions
Telegram’s recent Bot API update introduced paid messages, giving bot developers a new way to charge for specific interactions. This tutorial shows how to design, send, and verify paid messages in a production-friendly bot workflow.
Telegram Bot API 7.1 introduced paid messages, a practical feature for bots that need to monetize premium interactions without moving the user out of Telegram. If you build a bot that offers expert advice, on-demand content, concierge support, or digital goods, this update is worth understanding in detail.
This tutorial focuses on how paid messages fit into a bot architecture, how to implement them safely, and what to watch for when you start charging users inside your bot flow.
What paid messages are for
Paid messages let a bot gate a response or action behind payment. Instead of sending every output for free, you can:
- charge for a one-off premium reply
- unlock a special command or report
- sell access to a generated asset
- meter usage for compute-heavy features
A good use case is one where the value is immediate and self-contained. For example:
- a resume-review bot that charges for a detailed critique
- a market-data bot that sells a snapshot report
- a language tutor bot that unlocks advanced feedback
The key design idea is simple: the payment should buy a clearly defined result.
Before you code: model the transaction
Do not start by wiring payments into a command handler. Start by defining the business flow.
Ask these questions:
- What exactly is being sold?
- Is the user paying per request, per time window, or per bundle?
- What happens if the bot fails after payment?
- How do you prevent duplicate charges?
- How do you store and reconcile paid access?
A robust Telegram bot payment flow usually has these states:
requested— user asked for a premium actionpayment_pending— invoice or payment prompt sentpaid— payment confirmed by Telegram updatefulfilled— your bot delivered the premium resultrefunded_or_failed— payment failed or was reversed
If you do not track these states, you will eventually end up with missing deliveries or accidental double fulfillment.
Prerequisites
You will need:
- a bot created with BotFather
- a payment provider connected if your flow uses Telegram payments
- a backend that can receive updates via polling or webhook
- a database table for payment and fulfillment records
You should also already be comfortable handling common Bot API patterns like callback queries, inline keyboards, and message edits.
How paid messages fit into a bot flow
At a high level, the flow looks like this:
- User requests a premium action.
- Bot sends a payment prompt or invoice.
- Telegram confirms the payment via updates.
- Bot verifies the payment and marks the request as paid.
- Bot performs the premium action.
- Bot sends the result back to the user.
The exact API calls depend on your payment setup, but the architecture remains the same.
Implementation pattern: command, payment, fulfillment
A reliable pattern is to split your handler logic into three parts:
- request handler — creates the premium job and calculates price
- payment handler — verifies payment updates
- fulfillment handler — delivers the premium output
This keeps your bot from mixing side effects with chat logic.
1) Handle the user request
Suppose the user sends /report. Your bot should:
- validate that the user is allowed to buy the report
- generate a unique order ID
- store the order in your database
- send the payment prompt
Pseudo-code:
order_id = create_order(user_id=user.id, product="report", status="payment_pending")
send_invoice(
chat_id=user.id,
title="Premium Report",
description="A detailed analysis generated on demand.",
payload=order_id,
currency="USD",
prices=[{"label": "Premium Report", "amount": 499}]
)
The important part is the payload or equivalent order reference. That is how you later connect the payment to the correct request.
2) Verify the payment update
When Telegram notifies your bot that payment succeeded, do not immediately trust the chat context alone. Instead:
- read the payment payload/order ID
- load the order from your database
- confirm the amount and currency match expectations
- ensure the order is still unpaid
- mark it as paid atomically
That last step matters. If your update handler is retried or your webhook is delivered twice, you do not want to fulfill the same order twice.
Pseudo-code:
order = db.get_order(payload)
if not order:
reject("unknown order")
if order.status == "paid":
return # already processed
if order.amount != payment.amount or order.currency != payment.currency:
reject("payment mismatch")
with db.transaction():
db.mark_paid(order.id, payment_id=payment.id)
db.enqueue_fulfillment(order.id)
Use a transaction or an equivalent atomic update. That is the difference between a bot that survives retries and one that leaks revenue or duplicates work.
3) Fulfill the premium action
Once the order is marked as paid, generate and send the result.
For example:
report = build_report(order.user_id, order.parameters)
bot.send_message(chat_id=order.user_id, text=report)
db.mark_fulfilled(order.id)
If the fulfillment is expensive, move it to a background worker. That way your update handler stays fast and Telegram does not time out waiting for your server.
Handling retries and duplicate updates
Telegram bots must be idempotent. This is especially true for payment flows.
Make sure your handlers can safely process the same update more than once.
Use one or more of these guards:
- unique order IDs
- unique payment IDs stored in the database
- atomic status transitions
- idempotency keys for fulfillment jobs
A common approach is:
order_idis the business keyprovider_payment_idis the external payment keyfulfillment_job_idis the worker task key
Do not rely on message text or timestamps to determine whether payment has already been processed.
A practical database schema
A simple schema might look like this:
CREATE TABLE premium_orders (
id TEXT PRIMARY KEY,
user_id BIGINT NOT NULL,
product TEXT NOT NULL,
amount INTEGER NOT NULL,
currency TEXT NOT NULL,
status TEXT NOT NULL,
provider_payment_id TEXT,
created_at TIMESTAMP NOT NULL,
paid_at TIMESTAMP,
fulfilled_at TIMESTAMP
);
Useful indexes:
user_id, created_atfor history lookupsstatusfor queue processingprovider_payment_idfor reconciliation
If you sell multiple products, add a catalog table instead of hardcoding prices in your handlers.
Error handling strategy
Payments are not the place for vague failure handling. Define explicit outcomes.
If the payment succeeds but fulfillment fails
This is the hardest case. The order is paid, but the content was not delivered.
Your bot should:
- mark the order as paid
- retry fulfillment automatically
- notify the user that the result is being prepared
- provide a recovery path if retries keep failing
A good pattern is to store the order as paid_pending_fulfillment until the background job completes.
If the user pays the wrong amount
Reject it and keep the order open or ask the user to repurchase correctly, depending on your payment setup.
If the user initiates the same purchase twice
Return the existing open order instead of creating a new one, unless your product is intentionally repeatable.
Security notes for Telegram developers
A payment-enabled bot needs stricter controls than a simple chat bot.
- Never expose secret keys in client-side code.
- Verify all payment-related updates on the server.
- Do not trust user-supplied amount fields.
- Record every payment event with timestamps.
- Restrict admin commands that can modify order state.
If your bot offers digital goods, also think about replay prevention. Once an item is delivered, make sure it cannot be claimed again from the same order.
User experience tips
Monetization inside Telegram works best when the flow is clean and predictable.
Keep the payment prompt:
- short
- specific
- honest about what the user gets
- clear about pricing
Avoid surprise charges or ambiguous descriptions. Users should know exactly what they are buying before they pay.
After payment:
- confirm success immediately
- show an ETA if generation takes time
- provide a history command for past purchases
- offer support if the item is not delivered
Example workflow for a paid knowledge bot
Here is a complete example of a bot that sells a premium answer:
- User asks a question.
- Bot shows a short free preview.
- User taps “Unlock full answer.”
- Bot creates order
ORD-10291and sends a payment prompt. - Telegram confirms the payment.
- Bot marks the order paid.
- Background worker generates the full response.
- Bot sends the full answer and archives the order.
This flow is effective because it makes the value obvious before payment and keeps the bot responsive.
Testing the payment flow
Test more than the happy path.
Checklist:
- unpaid order remains unpaid if payment never arrives
- successful payment transitions to paid exactly once
- duplicate payment update does not duplicate fulfillment
- fulfillment failure retries correctly
- wrong currency or amount is rejected
- database crash during payment update does not corrupt order state
If possible, build tests around your order state machine. That is where most payment bugs hide.
When not to use paid messages
Paid messages are not ideal for every bot.
Avoid them when:
- the feature is too trivial to justify a charge
- the result is highly variable and hard to describe in advance
- the interaction requires long human involvement
- the user needs a subscription model instead of single purchases
In those cases, a separate billing model may be a better fit.
Final thoughts
Telegram Bot API’s paid-message capability is most valuable when it is treated as an engineering feature, not just a monetization button. The bots that do well with it are the ones that treat payments as a state machine: request, pay, verify, fulfill, and reconcile.
If you already have a bot with clear high-value actions, now is a good time to add paid flows. Start small, make the transaction idempotent, and test every failure case before you ship.
That discipline will save you from support headaches later and make your bot much easier to scale.