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.

Telegram15 min read

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 TypePermitted Payment RailIntegration Mechanism
Digital items, SaaS tiers, chat creditsTelegram Stars (XTR)createInvoiceLink (currency XTR, empty provider token) + openInvoice
Physical inventory, physical ticketing, offline servicesCredit Cards via Stripe / BotFather providerscreateInvoiceLink (fiat currency, provider token) + openInvoice
Non-custodial crypto, DeFi, on-chain mintsTON Connect / Crypto WalletsTON 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.

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.

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:

  • currency must be set to "XTR".
  • provider_token must 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 via refundStarPayment).
  • 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:

  1. Open @BotFather, enter /mybots, and select your bot.
  2. Navigate to Bot Settings > Payments.
  3. Select your preferred provider, such as Stripe, and complete the authorization flow.
  4. 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 sendTransaction returns, the wallet has merely broadcasted the payload. Set the client UI state to confirming and 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 validUntil parameter (typically 10 to 15 minutes). If the transaction is not detected on-chain within this window, transition the order state to expired to 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_amount matches your database record down to the integer unit (such as exact Stars or minor currency units like cents).
  • Ensure query.currency matches the expected asset code (XTR for 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_payment update 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 with TEST:. Pass this token to createInvoiceLink during staging. Use standard Stripe test cards (such as 4242 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:

  1. Add an intentional 11-second delay in your staging handler for pre_checkout_query.
  2. Confirm the Telegram checkout sheet closes gracefully with an error modal rather than hanging indefinitely.
  3. 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 StateSimulation MethodExpected Outcome
Webhook RedeliveryReplay 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 CancellationTap the close button on the native checkout sheet.The openInvoice promise resolves with cancelled; frontend state resets and no database order transitions occur.
Insufficient FundsAttempt 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 DropsSever 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 TierBaseline PriceStandard Scope
StarterFrom $700Single-purpose interface, Telegram authentication, Bot API connection
Standard$1,000–$1,500Multi-screen application, custom database models, user state management
ProFrom $2,000Complex 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

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.

Sources

More from the blog

Telegram · November 13, 2026

Telegram Bot vs Website: Which Is Better for Customer Support?

A structured decision framework comparing Telegram bots and website support layers across six factors to help you choose the right channel.

15 min read
Telegram · November 13, 2026

How Much Does a Custom Telegram Bot Cost for a Business?

A plain-language breakdown of every cost driver behind custom Telegram bot development — so you can budget confidently and evaluate quotes.

17 min read
Engineering · November 12, 2026

Case Study: The Payment Layer – A Policy and Approval Layer for AI-Agent Payments

An architectural breakdown of The Payment Layer, a policy and approval gateway engineered to enforce spending limits, isolation, and auditability on autonomous AI agents.

16 min read