Telegram Stars
Accept payments in Telegram Stars (XTR) — Telegram's native digital currency — directly inside Telegram. Use this when your customers already live in Telegram (bots, mini-apps, channels) and you want them to pay without leaving the app.
This rail uses a separate endpoint from the main Payments API and returns a real t.me/$invoice/... link you can attach to a message, inline keyboard, or mini-app button. The customer never sees a Vexutopia checkout page.
Prerequisites
- A LIVE API key. Test keys are rejected with
400 TELEGRAM_STARS_LIVE_ONLY. Stars are real money even at small amounts, so there is no sandbox mode. - Telegram Stars approved for your site. Stars is gated by a per-site approval like every other rail. Once approved, proceeds settle to your balance and are withdrawn like any other coin/network — you choose the destination wallet (TON included) when you request a withdrawal. No payout wallet needs to be configured up front.
Endpoint
POST https://vexutopia.com/api/v1/payments/telegram-starsAuthentication is the same as the rest of the API — pass your LIVE key in the X-API-Key header. See Authentication.
Request body
| Parameter | Type | Description |
|---|---|---|
amountrequired | string | When currency is "XTR", a whole number of stars (e.g. "1500") — the customer is charged that integer. When currency is "USD", a decimal dollar string (e.g. "1.00") that we ceil-convert to stars. |
currencyrequired | string | "XTR" to price in stars, or "USD" to price in dollars. Use XTR when you need an exact pack size. |
return_urlrequired | string | Where the customer is sent after the invoice closes. Telegram opens this in an in-app browser. |
customer_email | string | Optional, used for receipts and reconciliation. |
customer_name | string | Optional display name. Telegram does not show this on the invoice — used for your records only. |
customer_id | string | Optional merchant-side identifier round-tripped on the webhook. |
webhook_url | string | Where we POST status updates. Same shape and signature as every other rail. |
metadata | object | String key/value pairs round-tripped on the webhook payload. |
country | string | Optional ISO 3166-1 alpha-2 country code for analytics. |
With currency: "XTR", the customer pays the integer you send. The USD figure we store is accounting-only and locked at create. The USD path still works and still ceil-converts at the platform estimate — that conversion can change if the estimate changes, so pack SKUs should send XTR.
Example — exact star pack
curl -X POST https://vexutopia.com/api/v1/payments/telegram-stars \
-H "X-API-Key: vex_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"amount": "1500",
"currency": "XTR",
"customer_email": "[email protected]",
"return_url": "https://t.me/your_bot?start=order_1234",
"webhook_url": "https://yoursite.com/api/webhooks/vexutopia",
"metadata": { "order_id": "1234" }
}'Example — USD (ceil-converted)
curl -X POST https://vexutopia.com/api/v1/payments/telegram-stars \
-H "X-API-Key: vex_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"amount": "1.00",
"currency": "USD",
"return_url": "https://t.me/your_bot?start=order_1234"
}'Response
{
"id": "tx_a1b2c3d4e5f60718",
"status": "pending",
"amount": "1500",
"currency": "XTR",
"stars": 1500,
"checkout_url": "https://vexutopia.com/pay?session=tx_a1b2c3d4e5f60718",
"telegram_invoice_url": "https://t.me/$AbCdEf...",
"expires_at": "2026-05-09T23:30:00Z",
"created_at": "2026-05-09T22:30:00Z"
}A USD request still echoes amount and currency as you sent them (e.g. "1.00" / "USD") plus the computed stars count. That create-response shape is unchanged.
| Parameter | Type | Description |
|---|---|---|
id | string | Vexutopia transaction id. This is what the webhook references and what you pass to GET /v1/payments/{id}. |
telegram_invoice_url | string | The actual t.me/$invoice link to hand to the customer — attach to a button, send as a message, open from a mini-app. This is what you use. |
checkout_url | string | Vexutopia-hosted fallback page that wraps the same invoice. Useful if you also serve non-Telegram traffic; ignore otherwise. |
stars | integer | How many stars the customer is charged. Equals amount when you sent XTR; computed from amount when you sent USD. |
status | string | Always "pending" on creation. Watch the webhook for the terminal status (completed / failed / cancelled / expired). |
Inside a Telegram bot: attach the telegram_invoice_url to an inline keyboard button using the url field — Telegram opens the invoice natively. Do not redirect through an in-app browser; the native invoice UI is what makes Stars work.
Webhooks
Webhook delivery is identical to every other rail. We POST to your webhook_url with a payment.completed or payment.failed event. The top-level id, payment_id, and order_id fields are all aliases for the same Vexutopia transaction id you received in the create response.
Signature header, retry policy, and payload shape are documented in Webhooks.
Fees and settlement
- No separate per-payment processing fee appears on your transaction — the platform fee below is the per-payment fee.
- Vexutopia's platform fee on Stars is volume-tiered: 5% under $100K lifetime, 4% at $100K – $200K, 3% at $200K – $500K, and 2% above $500K. The Crypto On-Ramp rail steps down at the same volume thresholds; see Providers → Volume tiers for the full table.
- Stars proceeds settle to your Vexutopia balance and are withdrawn like any other coin or network — you choose the destination wallet (TON included, alongside every other supported network) when you request a withdrawal. No payout wallet needs to be configured up front. The USD equivalent used for fees and the dashboard is locked at invoice creation — the amount you receive in your chosen coin depends on its rate at withdrawal.
- Maturity: T+21. Each completed Stars sale becomes withdrawable 21 days after the customer paid, matching Telegram's customer-refund window. Until then the sale sits in the "Maturing" sub-line of your Stars balance card. Your dashboard's "Available to withdraw" figure is genuinely what's safe to pay out — it does not include Stars still subject to a customer refund.
- $50 fee per Telegram-issued refund. Customers can ask Telegram Support to refund a Stars payment. When that happens we record the refund on the transaction, decrement your pending Stars balance by the refunded amount plus the $50 equivalent, and surface it on the Refunds & Chargebacks page so you can keep track of it alongside disputes on other rails.
Errors specific to this endpoint
| Parameter | Type | Description |
|---|---|---|
TELEGRAM_STARS_LIVE_ONLY | 400 | You authenticated with a TEST key. Switch to a LIVE key — there is no sandbox for Stars. |
TELEGRAM_STARS_NOT_ALLOWED | 403 | Your account is not on the Stars allowlist (used during phased rollout). Contact support if you believe this is wrong. |
TELEGRAM_NOT_CONFIGURED | 503 | The platform-side Telegram bot is temporarily unavailable. Safe to retry — this is on our side, not yours. |
TELEGRAM_STARS_NOT_APPROVED | 403 | Telegram Stars is not approved for this site yet. Request approval from the dashboard. |
INVALID_AMOUNT | 422 | amount is zero, negative, or outside the 1–100,000 stars range (XTR integer, or USD after ceil conversion). |
PROVIDER_ERROR | 422 | Telegram rejected the invoice creation. The error message is included in the response — usually a transient Telegram API issue. |
Standard errors (auth, rate-limit, validation) behave the same as elsewhere — see Error Codes.
Next steps
- Payments API — the main endpoint for card, crypto, and regional rails.
- Webhooks — payload reference and signature verification.
- Error Codes — complete list with retry guidance.