This guide explains how to accept Telegram Stars deposits using the telegram_stars payment provider plugin, including refunds and reconciliation.
Deposits are paid through Telegram Bot API invoices in XTR and credited as chips. Withdrawals are not supported. Stars go back to a player only through the admin refund route.
How Telegram Stars Gets Enabled
telegram_stars is not one of the built-in payment provider types. It does not appear under Provider Type in the cashier settings until the plugin is active, and there is no need to add it by hand: activating the plugin creates the payment system for you, named Telegram Stars, with an empty configuration and both deposits and withdrawals off.
Setup has five steps, all of which are required.
1. Install and Activate the Plugin
The plugin source ships in the plugins/telegram-stars-provider directory of the codebase, but it is not part of the Docker image.
- Build the archive from that directory with
npm install,npm run build, thennpm pack. - In the admin sidebar, go to Plugins and click Upload Plugin, then choose the
.tgzfile. - Click Activate on Telegram Stars.
2. Enter the Configuration in the Cashier
Go to Settings → Cashier, edit the Telegram Stars provider, and fill in the fields under Update API Configuration.
Important: Enter these values in the cashier, not in Plugins → Settings. The plugin also shows a Settings form with the same fields, but invoices, webhook checks, refunds, and reconciliation all read the payment system’s configuration. Values saved only in the Settings form have no effect.
| Field | Key | Required | Default | Description |
|---|---|---|---|---|
| Bot Token | botToken | Yes | None | Creates invoices and processes refunds |
| Webhook Secret Token | webhookSecretToken | Yes | None | Telegram sends this in X-Telegram-Bot-Api-Secret-Token |
| Webhook Base URL | webhookBaseUrl | No | None | Only used by automatic webhook registration (see step 3) |
| Stars per Chip | starsPerChipRate | No | 1 | Stars charged for one chip |
| Minimum Deposit Stars | minDepositStars | No | 1 | Minimum invoice amount |
| Maximum Deposit Stars | maxDepositStars | No | None | Maximum invoice amount |
| Invoice Title | invoiceTitle | No | Poker chips | Telegram invoice title |
| Invoice Description | invoiceDescription | No | Deposit poker chips with Telegram Stars | Telegram invoice description |
| Test Mode | testMode | No | Off | Reserved. Nothing reads it. |
A deposit whose chip amount doesn’t convert to a whole number of Stars at the current Stars per Chip rate is refused.
The provider card may show No webhook signing secret configured. That badge doesn’t recognize webhookSecretToken, so it can be ignored once the secret is set. The check on incoming webhooks does use it.
3. Register the Webhook with Telegram
Important: Register the webhook yourself. The plugin contains automatic registration, but in this version it doesn’t take effect, because it looks for the bot token outside the payment system’s stored configuration. The server logs
Telegram Stars webhook not configured - botToken and webhookSecretToken are requiredat startup and after settings are saved. For the same reason, the plugin does not delete the webhook on shutdown or deactivation.
Call Telegram setWebhook with the same values the plugin would use:
curl -X POST "https://api.telegram.org/bot<bot-token>/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://<your-host>/api/v1/plugins/telegram_stars/webhook",
"secret_token": "<webhook-secret-token>",
"allowed_updates": ["pre_checkout_query", "message"],
"drop_pending_updates": false
}'
Without this step, invoices are created but payments can’t complete, because the pre-checkout query never reaches the server.
4. Enable Account Linking
Each payer must have a linked Telegram account, and that link must match the Telegram user paying. Linking is provided by the Telegram Mini App Authentication plugin, so install that as well.
5. Turn On Deposits
Back in Settings → Cashier, turn on Deposits for the provider. The method is hidden from players unless both the bot token and webhook secret are set. Telegram Stars is always removed from withdrawal methods.
The cashier feature toggle must also be on. See Feature Toggles Reference.
Deposit Flow
- The player chooses Telegram Stars in the cashier, which calls
POST /api/v1/cashier/depositwith methodtelegram_stars. - The server creates a pending deposit and a Telegram invoice, using the pending transaction ID as the invoice payload.
- The cashier opens the invoice inside Telegram when possible, otherwise it redirects to the
https://t.melink. - Telegram sends a
pre_checkout_query, which the server approves or rejects. - Telegram sends
successful_payment. The deposit is settled through the standard payment webhook pipeline, and the transaction’s external ID becomes the Telegram charge ID.
Pre-Checkout Rejections
The player sees one of these messages when a payment is rejected:
| Message | Cause |
|---|---|
Invalid Telegram Stars invoice | Missing fields, or the currency is not XTR |
Invoice has expired or was already processed | No matching pending deposit |
Account is not eligible for deposits | Account blocked or frozen |
Invoice amount does not match deposit amount | The amount differs at the current rate, for example after the rate changed |
Link your Telegram account before paying with Stars | The depositing account has no Telegram link |
Invoice payer does not match linked Telegram account | A different Telegram user is paying |
Webhook Errors
A missing or wrong secret returns 403 with TELEGRAM_STARS_WEBHOOK_ERROR, and other failures return 400 with the same code. Other Telegram updates are acknowledged with 200 and ignored.
During maintenance mode, this webhook returns 503 like other non-admin routes.
Refunds
There is no admin panel control for refunds. Send an API request from an authenticated admin session with a CSRF token:
POST /api/v1/plugins/telegram_stars/refunds/:transactionId
{ "reason": "Customer request" }
reason is optional. The route needs permission level a or a1.
The server then:
- Confirms the transaction is a completed Telegram Stars deposit.
- Confirms the user still has a linked Telegram account.
- Confirms the user’s balance covers the credited chips. If not, the refund is refused before Telegram is contacted.
- Calls Telegram
refundStarPaymentand records a marker in the plugin’s settings. - Creates and approves a local withdrawal that removes the chips, with the idempotency key
telegram-stars-refund:<chargeId>.
If Telegram accepts the refund but the local reversal fails, send the same request again. The marker prevents a second Telegram refund, and only the local reversal is retried.
| Result | Meaning |
|---|---|
status: "refunded" | Refund complete. Includes reversalTransactionId. |
status: "already_refunded" | The local reversal already exists. Nothing was changed. |
TELEGRAM_STARS_REFUND_ERROR | Refused. 404 if the transaction isn’t found, otherwise 400. |
Reconciliation
Reconciliation compares Telegram’s Star transactions with local completed deposits. It only reports differences and doesn’t change anything.
POST /api/v1/plugins/telegram_stars/reconcile
{
"from": "2026-06-18T00:00:00.000Z",
"to": "2026-06-19T00:00:00.000Z",
"offset": 0,
"limit": 100
}
All fields are optional, and the route needs the same permission as refunds. The two pairs of fields filter different sides:
| Field | Applies to | Notes |
|---|---|---|
from, to | Local deposits only | Up to 1000 deposits, newest first |
offset, limit | Telegram transactions only | limit is 1 to 100, default 100 |
The response includes telegramCount and localCount, plus:
| Field | Meaning |
|---|---|
missingLocal | Telegram charges with no matching local deposit in the selected range |
missingTelegram | Local deposits not in the selected Telegram page |
amountMismatches | Local chips, converted at the current rate, that differ from Telegram’s Stars amount |
Because the two sides are filtered separately, entries in missingLocal and missingTelegram can simply be outside the other side’s range. Check them against the wider history before treating them as real discrepancies.
Amounts are converted with the current Stars per Chip rate. After a rate change, older deposits can appear in amountMismatches, or the request can fail with TELEGRAM_STARS_RECONCILE_ERROR if an old amount no longer converts to whole Stars.
API Endpoints
| Method | Path | Permission | Description |
|---|---|---|---|
POST | /api/v1/plugins/telegram_stars/webhook | Webhook secret | Telegram updates |
POST | /api/v1/plugins/telegram_stars/refunds/:transactionId | Admin + CSRF | Refund a deposit |
POST | /api/v1/plugins/telegram_stars/reconcile | Admin + CSRF | Compare with Telegram |
Related
- Telegram Mini App Authentication — account linking, which deposits require
- Cashier & Payments — payment system configuration
- Plugin Management — installing plugins