Wholesale Telegram Stars and Telegram Premium over a REST API. Payment is up front: you top up a prepaid balance, the partner price of each order is debited from it, and you sell to your end customer at your own price.
"13.50", not 13.5. The currency of every amount is given in the
currency field. A string rather than a number is deliberate: amounts are computed with decimal arithmetic,
and converting them to float would distort the cents.POST /orders with a mandatory idempotency_key.
At that moment the partner price is debited from your balance.You take payment from the end customer yourself, in your own system. Your margin is the difference between your price and the partner price.
The price is the same for every partner. There are no tiers, no volume thresholds and no personal discounts, and nothing to negotiate: one number for everyone who connects.
Prices are denominated in USDT; no local-currency exchange rate enters the calculation. The value is recalculated in step with the market, so it is worth re-reading it from the catalog before you order.
Current prices — GET /products. The exact order amount is fixed in the response to
POST /orders; the price_per_star field in the catalog is for reference (6 decimals),
you do not need to multiply it yourself.
The balance is a prepaid purchasing balance: it can only be spent on orders and cannot be withdrawn. The account currency is US dollars (USDT).
How to top up. In the dashboard, choose a network (TON, TRC-20 or BEP-20) and an amount — the service will give you an exact amount down to the cent and an address. Send exactly that: TRC-20 and BEP-20 transfers have no comment field, so the payment is identified by its amount. Crediting is automatic, usually within a minute of network confirmation.
Activation. The first top-up starts at $10.00. Until it lands, the dashboard is
closed, no API key can be issued, and API requests are rejected with
403 partner_inactive.
Your remaining balance — GET /me, the balance field. If the balance is not enough, the order
is rejected straight away with 402 insufficient_balance: no money is reserved and the order
does not hang waiting.
Base: https://pay.tgsuperstars.com/api/partner/v1. Authentication:
Authorization: Bearer pk_live_... (the key is issued in the dashboard; optionally
an IP whitelist per key). Machine-readable spec:
openapi.json.
Idempotency: the same idempotency_key in POST /orders →
the same order and exactly one debit. Retrying a request after a timeout is safe — this is the main way
to avoid losing or duplicating an order.
curl -H "Authorization: Bearer $KEY" https://pay.tgsuperstars.com/api/partner/v1/me
{
"partner_id": 100200300,
"status": "active",
"balance": "42.50",
"currency": "USD",
"pricing": {"note": "current prices — GET /products"},
"limits": {"api_rate_limit": {"per_minute": 120, "burst": 30},
"stars_min_per_order": 50,
"stars_max_per_order": 50000}
}
curl -H "Authorization: Bearer $KEY" https://pay.tgsuperstars.com/api/partner/v1/products
{
"currency": "USD",
"stars": {"price_per_1000": "15.15", "price_per_star": "0.015150",
"currency": "USD", "max_per_order": 50000},
"premium": {"3": {"partner_price": "12.11", "currency": "USD"},
"6": {"partner_price": "16.15", "currency": "USD"},
"12": {"partner_price": "29.28", "currency": "USD"}}
}
If a price is temporarily unavailable, you get
{"unavailable": true, "reason": "cost_unavailable"} instead of prices — this is not an HTTP error
but a straight signal that "we are not selling right now". An order will not be accepted at that moment either.
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"type":"stars","username":"@durov"}' https://pay.tgsuperstars.com/api/partner/v1/validate/recipient
For premium, the check also tells you whether the recipient already has a subscription —
that saves you an order that would end in an already_premium error.
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"type":"stars","idempotency_key":"ord-1","params":{"quantity":100,"recipient":"@durov"}}' https://pay.tgsuperstars.com/api/partner/v1/orders
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"type":"premium","idempotency_key":"ord-2","params":{"months":3,"recipient":"@durov"}}' https://pay.tgsuperstars.com/api/partner/v1/orders
Valid Premium terms are 3, 6 and 12 months. There are no other order types:
type accepts only stars and premium.
{
"order_id": "PA-12345",
"type": "stars",
"status": "processing",
"partner_price": "1.53",
"currency": "USD",
"retail": null,
"quantity": 100,
"recipient": "@durov",
"created_at": "2026-08-10T18:20:31+03:00",
"refunded": false
}
partner_price — the amount debited from your balance, as a string. On archived orders
created before 2026-08-10 it is a number in rubles with currency: "RUB";
go by currency, not by the type of the value.retail — always null: the website's retail price is in rubles,
which has no place in a dollar response. An explicit null rather than zero, so that nobody
reads it as "free".quantity — the number of stars for stars and the number of months
for premium. The minimum star order is 50; anything less
is rejected with bad_quantity before any debit.GET /orders/{id} and
GET /orders?status=&type=&from=&to=&cursor=&limit=.
Statuses: processing | completed | partial | canceled | failed. Outgoing webhooks
(order.completed | order.failed | order.refunded) are signed with the header
X-Signature: hex(hmac_sha256(body, your webhook_secret)) — verify the signature
and handle them idempotently (delivery is "at least once").
The format depends on where the error came from. Order processing errors arrive flat:
{"code": "insufficient_balance", "detail": "Insufficient balance"}
Request-level errors — authentication, rate limit, unknown type,
a missing idempotency_key — are the same object, but nested in the
detail field:
{"detail": {"code": "bad_type", "detail": "type ∈ stars|premium"}}
The difference is historical and kept on purpose, so as not to break existing
clients. A reliable parse: take detail, and if it is an object, read
code from it, otherwise from the root.
| HTTP | code | What it means |
|---|---|---|
| 401 | unauthorized | Missing or invalid Bearer key |
| 403 | ip_not_allowed | IP not in the key's whitelist |
| 403 | partner_inactive | Dashboard not activated — a first top-up starting at $10.00 is required |
| 429 | rate_limited | Rate limit exceeded — reduce your request rate |
| 400 | idempotency_required | No idempotency_key passed in POST /orders |
| 400 | bad_type | type is neither stars nor premium |
| 400 | bad_quantity / bad_months | Invalid number of stars or subscription term |
| 400 | recipient_required / recipient_not_found | Recipient not specified or not found |
| 400 | already_premium | Recipient already has Premium |
| 402 | insufficient_balance | Insufficient balance — top up your account |
| 502 | resolver_error | Recipient resolution failed — try again later |
| 503 | product_unavailable | Product temporarily unavailable |
/validate/* — 30 per minute.What happens to Stars if delivery fails? We treat it the same way as retail: when the delivery network is down, orders queue up and are delivered once it is back — no money is lost.
I retried after a timeout — will I be charged twice? No, not if you passed the same
idempotency_key: you get the same order back and there is still only one debit.
I sent an amount that was not exact to the cent — what now? The payment is not identified automatically and goes to manual review. Contact support at @tg_super_support_bot with the transaction hash.
Support: @tg_super_support_bot — for integration and payment questions. You support your own end customers.