How to Add Payments to Your Telegram Mini App (Stars, Cards and Crypto)
Learn how to add Telegram Stars, card processing, and crypto payments to your Telegram Mini App with complete backend verification and production hardening.
Payment Rails in Telegram: Stars, Cards, or Crypto
Selecting a payment rail for a Telegram Mini App is not merely a technical choice; it is a platform compliance requirement governed by Telegram, Apple App Store, and Google Play policies. Implementing the wrong payment method risks bot suspension or client-side checkout blocks on iOS and Android devices.
The Platform Rules
Telegram enforces distinct rails depending on the legal and operational nature of the item being sold:
- Digital Goods and Services (Telegram Stars): Under Telegram Stars guidelines, all virtual products—including SaaS access, digital media, digital upgrades, and platform features—must use Telegram Stars (
XTR). End users purchase Stars through in-app purchases on iOS and Android, or via @PremiumBot on desktop and web interfaces. Attempting to route digital utility checkouts to external credit card processors bypasses app store rules and leads to immediate client-side rejection. - Physical Goods and Real-World Services (Credit Cards via BotFather): When selling physical products, delivery items, or in-person bookings, you must use standard payment gateways connected via BotFather, such as Stripe. Under Telegram Bot Payments documentation, Telegram takes zero commission on these transactions, and payments clear directly into your merchant account.
- Web3 Native and On-Chain Transfers (TON Connect): Decentralized applications, token transfers, non-custodial wallet interactions, and smart contract calls must adhere to the Telegram Blockchain Guidelines. Wallets must connect via TON Connect rather than handling raw private keys. Crypto rails cannot be used as an evasive workaround to charge for off-chain digital application utilities.
Payment Rail Decision Matrix
| Deliverable Type | Permitted Payment Rail | Integration Mechanism |
|---|---|---|
| Digital items, SaaS tiers, chat credits | Telegram Stars (XTR) | createInvoiceLink (currency XTR, empty provider token) + openInvoice |
| Physical inventory, physical ticketing, offline services | Credit Cards via Stripe / BotFather providers | createInvoiceLink (fiat currency, provider token) + openInvoice |
| Non-custodial crypto, DeFi, on-chain mints | TON Connect / Crypto Wallets | TON Connect SDK + RPC indexing webhooks |
Choosing the compliant rail before writing integration code ensures your Mini App functions without payment failures across web, desktop, and mobile operating systems.
Integrating Telegram Stars with createInvoiceLink and openInvoice
Adding native Telegram Stars payments to your Mini App relies on a split architecture: your backend requests a unique payment link from the Telegram Bot API, and your frontend renders the native payment modal using the Telegram WebApp SDK.
Generating the Invoice Link on the Backend
Never construct raw invoice parameters directly on the frontend. When a user initiates a checkout in your Mini App, make an authenticated API call to your backend server. Your backend then invokes the Bot API method createInvoiceLink.
For Telegram Stars transactions, Telegram requires two specific parameter rules:
currencymust be set to"XTR".provider_tokenmust be an empty string ("").
Here is a backend implementation using Node.js and TypeScript:
// POST /api/checkout/stars
export async function createStarsInvoice(orderId: string, starsAmount: number): Promise<string> {
const response = await fetch(`https://api.telegram.org/bot${process.env.BOT_TOKEN}/createInvoiceLink`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: "Premium Feature Access",
description: "Unlock full analytics inside the Mini App",
payload: JSON.stringify({ orderId }), // Keep payload lean: internal order reference only
currency: "XTR",
prices: [{ label: "Premium Access", amount: starsAmount }], // Integer amount in Stars
provider_token: "", // Empty string is mandatory for Telegram Stars
}),
});
const data = await response.json();
if (!data.ok) {
throw new Error(`Failed to create Stars invoice: ${data.description}`);
}
return data.result; // Returns https://t.me/$... invoice link
}
### Launching the Native Checkout Sheet
Once your backend returns the invoice link, pass it directly to the Telegram Mini Apps SDK method [`openInvoice`](https://core.telegram.org/bots/webapps#initializing-mini-apps):
```typescript
// Client-side Mini App checkout trigger
function handlePurchase(invoiceUrl: string, orderId: string) {
window.Telegram.WebApp.openInvoice(invoiceUrl, (status) => {
switch (status) {
case "paid":
// Show pending spinner, NOT immediate fulfillment
setCheckoutState("verifying");
pollBackendOrderStatus(orderId);
break;
case "cancelled":
setCheckoutState("idle");
break;
case "failed":
displayError("Payment failed. Please try again.");
break;
}
});
}
### Why the `openInvoice` Callback Is Not Proof of Payment
The callback parameter `status === 'paid'` runs entirely on the client device. It confirms only that the Telegram UI closed after the user completed the purchase flow. It is vulnerable to client-side manipulation, network drops, or race conditions.
Never grant access to digital goods or mark orders as fulfilled based solely on `openInvoice(url, callback)`.
### Designing Smooth Verification UX
To ensure a seamless user experience:
1. When `status === 'paid'` fires, transition the Mini App UI to an optimistic loading screen ("Confirming transaction with Telegram...").
2. Establish a lightweight polling loop or a WebSocket/Server-Sent Events (SSE) connection against your backend to query the internal order state.
3. Only display the final success screen and unlock the paid feature once your backend marks the order as fulfilled after validating Telegram's authoritative webhook events.
## Handling pre_checkout_query and successful_payment on the Backend
Telegram does not complete a transaction in a single request. When a user approves an invoice inside a Telegram Mini App, the Telegram payments engine executes a two-stage server-side lifecycle via your bot webhook: an authorization check (`pre_checkout_query`) followed by a definitive confirmation message (`successful_payment`).
### The 10-Second Rule: Answering pre_checkout_query
Before charging the user, Telegram dispatches an update containing a `pre_checkout_query` to your webhook. Your backend has exactly 10 seconds to validate the order details and respond using the [answerPreCheckoutQuery](https://core.telegram.org/bots/api#answerprecheckoutquery) method. If your server takes longer than 10 seconds or fails to return `{ "ok": true }`, Telegram automatically aborts the transaction and displays an error message to the user.
Your validation pipeline must run three checks before clearing the transaction:
1. **Order state**: Look up the order using the `invoice_payload` and verify that its status is strictly pending.
2. **Amount and currency match**: Verify that `total_amount` and `currency` match your database record to the exact integer unit. Never rely on client-supplied values.
3. **Availability**: Confirm the digital item, subscription tier, or inventory is still available for that user.
```typescript
// Validating and answering pre_checkout_query
bot.on('pre_checkout_query', async (ctx) => {
const { id, invoice_payload, total_amount, currency } = ctx.preCheckoutQuery;
const order = await db.order.findUnique({ where: { id: invoice_payload } });
if (!order || order.status !== 'PENDING') {
return ctx.answerPreCheckoutQuery(false, {
error_message: 'This order is no longer valid or has already been processed.'
});
}
if (order.amount !== total_amount || order.currency !== currency) {
return ctx.answerPreCheckoutQuery(false, {
error_message: 'Price mismatch detected. Please regenerate your invoice.'
});
}
// Clear checkout within the 10-second limit
return ctx.answerPreCheckoutQuery(true);
});
Capturing successful_payment for Fulfillment
Once the charge clears on Telegram's side, your bot receives a standard update containing a message with a successful_payment object. This update is your single source of truth for payment completion.
The payload contains:
telegram_payment_charge_id: Telegram's internal payment reference (required to execute refunds viarefundStarPayment).provider_payment_charge_id: The external processor's ID (present when using Stripe or external providers).invoice_payload: Your internal order ID.
Your fulfillment logic must be strictly idempotent. Webhook deliveries can retry if network delays prevent your server from returning an HTTP 200 OK in time. Store the telegram_payment_charge_id in your database, execute fulfillment inside an atomic database transaction, and transition the order state so redelivered webhooks do not trigger duplicate credits.
Payments are where Mini Apps break in production under webhook redeliveries, edge cases, and network timeouts. We have shipped Stars and crypto checkout flows across production platforms like TGDirectory and ADPORTAL, and can add a hardened checkout pipeline to yours. If you want production-tested payment rails for your project, contact our engineering team.
Accepting Credit Cards for Physical Goods via BotFather Providers
If your Mini App sells physical merchandise—such as apparel, packaged goods, or printed materials—you can process standard credit and debit cards inside Telegram's native checkout interface using an integrated payment processor.
Connecting Stripe in BotFather
To connect a payment provider, configure your merchant credentials directly through BotFather:
- Open @BotFather, enter
/mybots, and select your bot. - Navigate to Bot Settings > Payments.
- Select your preferred provider, such as Stripe, and complete the authorization flow.
- BotFather provides two separate tokens: a sandbox token prefixed with
TEST:and a production token.
Store these provider tokens in your server environment variables. Never expose tokens to the client-side Mini App bundle.
Generating Fiat Invoices with Delivery Details
When you add payments to telegram mini app workflows for physical goods, call the Bot API method createInvoiceLink. Unlike Stars transactions, fiat card checkouts require your gateway's provider_token, an ISO 4217 currency code, and pricing defined in minor units (such as cents for USD):
const invoiceLink = await bot.api.createInvoiceLink({
title: "Studio Cotton Hoodie",
description: "Heavyweight cotton hoodie with embroidered logo",
payload: JSON.stringify({ orderId: "ord_10482" }),
provider_token: process.env.STRIPE_LIVE_TOKEN,
currency: "USD",
prices: [{ label: "Hoodie", amount: 6500 }], // $65.00 in cents
need_name: true,
need_phone_number: true,
need_shipping_address: true,
is_flexible: false, // Set to true to calculate shipping based on address
});
Your Mini App frontend receives this URL and opens the native payment sheet by passing it to Telegram.WebApp.openInvoice.
Telegram Fees and Policy Enforcement
According to the official Telegram Bot Payments documentation, Telegram collects zero commission on physical transactions routed through external card processors. You only pay standard merchant processing fees assessed directly by your payment gateway.
However, platform policy strictly limits where you can use card processors. Under the Telegram Stars guidelines, card providers like Stripe cannot be used for digital goods, downloadable assets, premium features, or virtual memberships. Digital items must use Telegram Stars to comply with mobile app store distribution rules. Using a telegram payment provider stripe integration for digital products risks immediate bot suspension. For physical items, this rail provides the core checkout infrastructure for building an e-commerce store inside Telegram.
Adding Crypto Payments via TON Connect and Webhooks
When accepting cryptocurrency in a Telegram Mini App, projects must adhere to Telegram's blockchain guidelines, which mandate TON Connect as the official standard for external wallet interactions. Mini Apps should never ask users to enter seed phrases or private keys directly in the webview. Instead, integrate @tonconnect/ui or @tonconnect/ui-react to trigger standard connection flows with non-custodial wallets like Tonkeeper, MyTonWallet, or Telegram Wallet.
Processor Webhooks vs. Direct On-Chain Verification
You can verify crypto checkouts using two primary architectural patterns:
- Third-Party Payment Processors: A dedicated payment gateway generates a hosted checkout or address, monitors block confirmations, and posts a signed webhook payload to your backend once the transaction settles.
- Direct Transfers via TON Connect: The Mini App crafts a transaction payload directly inside the user's connected wallet, sending TON or Jettons to your treasury address with a unique order ID serialized in the transaction comment.
Asynchronous Checkout Flow
Unlike credit cards or Stars, on-chain transfers are asynchronous. Network latency, gas fee variations, and block indexing mean you cannot block an HTTP request while waiting for finality.
// Constructing a TON Connect transfer payload with an order comment
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 600, // 10-minute TTL
messages: [
{
address: "EQB...MERCHANT_TREASURY_ADDRESS",
amount: "2500000000", // 2.5 TON in nanotons
payload: "te6cckEBAQEAAgAAAE8qUTg=", // Base64 BOC containing the order ID
},
],
};
await tonConnectUI.sendTransaction(transaction);
Managing State and Confirmations
To prevent stuck checkouts and protect fulfillment integrity:
- Decouple Client Feedback from Verification: When
sendTransactionreturns, the wallet has merely broadcasted the payload. Set the client UI state toconfirmingand poll your backend via server-sent events (SSE) or a status endpoint. Never fulfill an order based solely on client-side promises. - Verify On-Chain Data on the Backend: Use a TON indexer, RPC node, or webhook service to ingest confirmed blocks. Verify that the destination address matches your treasury, the received nanotons match the price, and the comment BOC decodes to your active order ID.
- Set Explicit Timeouts: Include a
validUntilparameter (typically 10 to 15 minutes). If the transaction is not detected on-chain within this window, transition the order state toexpiredto prevent execution against outdated price quotes.
Note: Cryptocurrency acceptance involves tax, regulatory, and reporting requirements depending on your jurisdiction; this technical guide does not constitute legal or financial advice.
Production-Hardening Checklist for Telegram Checkouts
In production Telegram mini app payments, edge cases quickly create accounting discrepancies and duplicate provisioning. Live applications—such as Telegram Channels selling featured placements paid in Telegram Stars or crypto—demand strict server-side verification. Client-side callbacks from openInvoice are visual triggers only and must never be treated as proof of payment.
Your backend architecture should implement the following hardening checklist to safeguard every transaction.
1. Payload Security: Store Opaque Identifiers Only
Never store product names, discount calculations, or prices in the payload parameter when generating an invoice with createInvoiceLink. An invoice payload is easily inspected. Instead, pass strictly an internal, opaque order UUID:
{
"payload": "order_9f8c1b2e-4b7a-4c28-9d82-8a9e62e15bc3"
}
When processing incoming Bot API updates, fetch the pricing, buyer account, and item entitlements directly from your own database using this ID.
2. Strict Price and Currency Verification
When Telegram issues a pre_checkout_query, your bot server must respond within 10 seconds using answerPreCheckoutQuery. Before approving:
- Verify that
query.total_amountmatches your database record down to the integer unit (such as exact Stars or minor currency units like cents). - Ensure
query.currencymatches the expected asset code (XTRfor Stars, fiat currency codes for card providers). - Confirm that inventory, subscription seats, or featured placements are still available.
If any check fails or the cart has expired, answer immediately with ok: false and a user-facing explanation.
3. Idempotent Order Fulfillment
Telegram automatically retries webhook delivery if your server takes too long to respond or experiences network interruptions. To prevent crediting a balance multiple times:
- Wrap entitlement activation inside an ACID database transaction.
- Apply a unique database constraint on
telegram_payment_charge_id. - If a
successful_paymentupdate arrives with an existing charge identifier, return HTTP 200 immediately without re-running fulfillment logic.
4. Persist Charge IDs Before Entitlement Activation
Never grant access to digital items before persisting the receipt. Store both telegram_payment_charge_id and provider_payment_charge_id in your database prior to updating the user's role or unlocking digital access. If your downstream fulfillment pipeline encounters an error, you retain the immutable transaction IDs required for manual ledger reconciliation.
5. Automated and Manual Refunds via refundStarPayment
For customer disputes or downstream provisioning failures, implement the official refundStarPayment method documented in the Telegram Bot API. Pass the customer's Telegram user_id and the recorded telegram_payment_charge_id. Telegram will reverse the charge, return the Stars to the user's balance, and invalidate the payment record.
End-to-End Testing Across Sandbox and Test Modes
Payment implementations must be tested under degraded network conditions and deliberate failure states before opening checkouts to live users.
1. Sandbox Configuration for Cards and Stars
- BotFather Test Providers: For card checkouts, message
@BotFather, open Bot Settings > Payments, and connect a sandbox provider such as Stripe Test. BotFather issues a provider token prefixed withTEST:. Pass this token tocreateInvoiceLinkduring staging. Use standard Stripe test cards (such as4242 4242 4242 4242) to simulate approved charges, 3D Secure challenges, and card declines without moving real money. - Telegram Stars Testing: Telegram lets developers test Stars workflows by running clients against Telegram's test environment (test data centers). In this mode, accounts receive test Stars for validation. If testing in production environments, run initial integration checks using 1-Star purchases ($0.02 nominal value) to verify the pipeline.
2. Simulating Network Delays and Timeouts
Telegram enforces a strict 10-second timeout on pre_checkout_query. If your server does not respond via answerPreCheckoutQuery within this window, the checkout modal aborts automatically.
Test this boundary by injecting artificial network delays:
- Add an intentional 11-second delay in your staging handler for
pre_checkout_query. - Confirm the Telegram checkout sheet closes gracefully with an error modal rather than hanging indefinitely.
- Ensure your server catches unhandled promises, releases any reserved stock or order locks, and logs the timeout without mutating user balances.
3. Redelivery Resilience and Edge State Verification
Telegram's Bot API guarantees at-least-once delivery, meaning network blips can cause duplicate webhook updates. Test the following edge states:
| Edge State | Simulation Method | Expected Outcome |
|---|---|---|
| Webhook Redelivery | Replay the same successful_payment update payload twice against your backend. | The first call marks the order paid and provisions access. The duplicate call matches the recorded telegram_payment_charge_id, returns 200 OK, and prevents duplicate fulfillment. |
| User Cancellation | Tap the close button on the native checkout sheet. | The openInvoice promise resolves with cancelled; frontend state resets and no database order transitions occur. |
| Insufficient Funds | Attempt a checkout with an account carrying zero Stars or an empty test card. | The native UI rejects the payment before dispatching pre_checkout_query, keeping server state untouched. |
| Network Drops | Sever client network connectivity immediately after authorization. | Because Telegram handles the transaction server-to-server, successful_payment still executes on your backend. When the user reconnects, your Mini App checks order status via your API and displays the confirmation. |
Cost to Add Payments to a Mini App and Next Steps
Building a compliant, secure checkout system requires careful orchestration between client-side SDK events, Bot API webhooks, and your database. At WEB3 Build Studio, we engineer production-ready payment infrastructure using modular building blocks and AI-assisted development workflows to keep pricing fixed and execution fast.
Fixed-Price Mini App Tiers
Every project receives a fixed price after a brief technical scoping discussion. Base Mini App packages include custom UI/UX design, full-stack engineering, production deployment, and 30 days of included bug fixes:
| Mini App Tier | Baseline Price | Standard Scope |
|---|---|---|
| Starter | From $700 | Single-purpose interface, Telegram authentication, Bot API connection |
| Standard | $1,000–$1,500 | Multi-screen application, custom database models, user state management |
| Pro | From $2,000 | Complex business logic, admin dashboards, high-concurrency architecture |
Because payment requirements depend on your catalog and product type—ranging from digital Telegram Stars and BotFather provider tokens for physical goods to non-custodial TON Connect crypto transactions—payment processing is scoped and priced as a dedicated add-on module to your base tier.
Hosting and Infrastructure Maintenance
Financial integrations require consistent webhook delivery and robust server uptime. We host and maintain Mini Apps on our studio servers for a flat rate of $79 per month. This care plan covers:
- High-performance server hosting and managed SSL certificates
- Automated daily database backups
- Continuous uptime monitoring and incident alerting
- Security patches and dependency updates
- Routine maintenance to ensure compatibility with Telegram Bot API updates
Related Resources
To prepare your monetization strategy and architecture, explore our related technical guides:
- Our Telegram Stars monetization guide for pricing strategies and compliance rules
- Our step-by-step engineering guide on how to build a Telegram Mini App
- Our detailed breakdown on building an e-commerce store inside Telegram
Start Your Implementation
Payments are where Telegram Mini Apps face the highest failure rate if webhooks, payload validation, and idempotency checks are not handled correctly. We can integrate Stars, credit card rails, or crypto checkouts into your existing software with end-to-end testing across sandbox and live environments.
Send us your Mini App specifications at https://web3buildstudio.com to receive a fixed quote and technical delivery roadmap.
Frequently asked questions
Can I use Stripe inside a Telegram Mini App?
Yes, you can use Stripe in a Telegram Mini App. Telegram supports Stripe directly as an integrated payment provider through BotFather, which allows you to generate invoices using sendInvoice or createInvoiceLink with your Stripe provider token. Alternatively, because a Mini App runs standard web technologies like React or Next.js, you can embed Stripe Elements or redirect users to a Stripe Checkout session. Keep in mind that platform rules, such as Apple App Store and Google Play guidelines, generally require Telegram Stars for digital goods, while Stripe is standard for physical products or services. This is not legal or compliance advice.
Do I need a provider token for Stars?
No, you do not need a provider token to accept Telegram Stars. Unlike traditional fiat payment gateways configured via BotFather (such as Stripe or Payme), Telegram Stars operate directly through Telegram's internal ledger. When creating an invoice link via createInvoiceLink or sending an invoice with sendInvoice, you set the currency field to "XTR" and leave the provider_token parameter blank or empty. Telegram routes the checkout through its native purchase flow, charging the user's Stars balance. Once the transaction completes, Telegram delivers the pre_checkout_query and successful_payment service updates to your bot's backend.
Is the openInvoice callback enough to confirm payment?
No, the client-side openInvoice callback in the Telegram Web Apps SDK is not enough to confirm a payment. The callback only indicates that the payment modal was closed or reported a paid status on the client. Relying solely on client events exposes your system to spoofing or interrupted connections. Secure confirmation must happen on your server. Telegram sends a pre_checkout_query webhook to your bot, which your backend must approve within ten seconds. After processing, Telegram sends a successful_payment update containing the telegram_payment_charge_id, total amount, and your custom payload. Only update user balances or grant access after verifying this server-side update.
How do I refund a Stars payment?
To refund a Telegram Stars payment, use the refundStarPayment method provided by the Telegram Bot API. This endpoint requires two parameters: the Telegram user_id of the buyer and the telegram_payment_charge_id generated during the original transaction. You capture this charge ID from the successful_payment payload on your backend when the purchase initially succeeds. Calling this API reverses the transaction, returns the Stars directly to the user's Telegram balance, and cancels the bot's incoming credit for that transaction. Keep records of these charge IDs in your database (such as PostgreSQL) so your team or automated support workflows can issue programmatic refunds when needed.
Can I accept crypto in a Mini App?
Yes, you can accept cryptocurrency directly inside a Telegram Mini App. Because Mini Apps run standard web technologies, you can integrate Web3 wallet connection libraries. For the TON ecosystem, TON Connect allows users to link Telegram's native @wallet, Tonkeeper, or OpenMask. For other networks, such as Solana, you can embed wallet adapters like Phantom or Solflare to execute on-chain transactions. Alternatively, your backend can generate dedicated deposit addresses and listen for on-chain transaction confirmations. When handling crypto transactions, ensure your infrastructure securely verifies on-chain finality before delivering products or services. Note that this information does not constitute financial, investment, or legal advice.
How do I test payments without real money?
You can test payments across all methods using developer environments without spending real capital. For Telegram Stars, connect your bot to Telegram's dedicated Bot API test environment, or use the /settestmode switch in BotFather to test transactions with sandbox Stars. For card payments through Stripe, configure your bot with a Stripe test provider token obtained from BotFather and submit standard test card credentials. For crypto integrations, connect your Mini App and backend nodes to public testnets or devnets—such as Solana Devnet or TON testnet—and request free test tokens from network faucets. This allows you to validate end-to-end checkout flows safely before launch.