Back to Articles
Payments & Stars

Integrating Telegram Stars Payments: Full Backend & Webhook Guide

Telegram Stars have revolutionized in-app monetization across iOS, Android, and Web clients. Whether selling digital courses, exclusive community access, or virtual game items, Stars provide a zero-friction, native checkout experience with 100% compliance on mobile app stores.

1. Generating a Stars Invoice with createInvoiceLink

To initiate a Telegram Stars payment inside a Mini App or bot, generate an invoice link using Bot API method createInvoiceLink. Set the currency to XTR (the official currency code for Telegram Stars):

async function generateStarsInvoice(botToken, { title, description, payload, starsAmount }) {
  const url = `https://api.telegram.org/bot${botToken}/createInvoiceLink`;
  
  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      title: title,
      description: description,
      payload: JSON.stringify(payload),
      currency: 'XTR',
      prices: [{ label: title, amount: starsAmount }]
    })
  });

  const data = await response.json();
  if (!data.ok) throw new Error(data.description);
  return data.result; // Returns https://t.me/$invoice_slug
}

2. Opening the Payment Dialog in Telegram Mini Apps

Inside the frontend Mini App, open the generated invoice link seamlessly using the Telegram WebApp SDK method openInvoice:

function buyWithStars(invoiceLink) {
  if (window.Telegram?.WebApp) {
    window.Telegram.WebApp.openInvoice(invoiceLink, (status) => {
      if (status === 'paid') {
        console.log('Payment successful! Granting digital access...');
        showSuccessModal();
      } else if (status === 'cancelled') {
        console.log('User cancelled checkout.');
      } else {
        console.error('Invoice error:', status);
      }
    });
  } else {
    window.open(invoiceLink, '_blank');
  }
}

3. Handling pre_checkout_query and successful_payment Webhooks

Security is paramount. You must answer every pre_checkout_query within 10 seconds to authorize the transaction, and listen for successful_payment to fulfill the order securely on your server.

export default {
  async fetch(request, env) {
    const update = await request.json();

    // Step A: Validate pre_checkout_query
    if (update.pre_checkout_query) {
      const queryId = update.pre_checkout_query.id;
      
      // Verify stock or user status in database
      await fetch(`https://api.telegram.org/bot${env.BOT_TOKEN}/answerPreCheckoutQuery`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          pre_checkout_query_id: queryId,
          ok: true
        })
      });
      return new Response('OK');
    }

    // Step B: Fulfill order on successful_payment
    if (update.message?.successful_payment) {
      const payment = update.message.successful_payment;
      const orderPayload = JSON.parse(payment.invoice_payload);
      
      await fulfillOrder(orderPayload, payment.telegram_payment_charge_id);
    }

    return new Response('OK');
  }
};

4. Converting Stars to TON or Ad Credits

Earned Stars can be converted into TON cryptocurrency via Fragment.com after a 21-day escrow period, or used directly to run targeted Telegram Ads with subsidized CPM rates.