Integration
A price that means the same thing when they press send
USDT on TON is a jetton — a token contract rather than the native coin — accepted inside Telegram through the same wallet flow as TON itself. It converts better than native TON for commerce because the quoted amount does not move between the quote and the payment. It is irreversible on confirmation.
USDT on TON integration: auth, limits and availability
- Auth model
- None required
- Balance location
- A per-owner jetton wallet contract, not the main account
- GCC availability
- Open to any TON wallet holding USDT; no onboarding
- Data flow
- 5 hops, worker-mediated
As of 2025-10-01, Telegram Bot API 13.4
Why this integration exists
Quoting a price in a volatile asset creates a problem that has nothing to do with technology. A storefront quotes 12 TON, the customer thinks about it for ninety seconds, and the value has moved. Small movements are tolerable; visible ones make the customer feel they are gambling on a purchase, and abandonment climbs accordingly.
A stablecoin removes that entirely. Twenty USDT is twenty dollars when quoted and twenty dollars when paid, and the customer's decision is about the product rather than about timing. For any commerce use — a storefront, a subscription, a service payment — this is usually the single biggest conversion factor on the payment step, ahead of anything about the checkout interface.
The mechanics differ from native TON in ways that matter to the implementation. A jetton balance is not held on the account; it lives in a per-owner jetton wallet contract that must be resolved first. Decimals are contract-defined and are not the same as TON's. And the sender still needs a little native TON to pay for the transfer, which produces a specific and common failure: a customer with plenty of USDT and no TON, unable to pay, with an error message that explains nothing.
How the data actually moves
There is no authentication to a stablecoin. Payments are verified by reading the chain, exactly as with native TON, and any API key involved belongs to the chain data provider rather than to the token. What replaces authentication is matching: the backend records what it expects before asking for payment, and recognises the transfer when it appears.
Auth model: No authentication
Their limits, and what they mean for you
Jetton balances live in a per-owner jetton wallet contract, not on the owner's main account.
The jetton wallet address is derived for each owner before any balance can be read. Reading the base account and seeing nothing is the standard first confusion.
Jetton decimals are defined by the token contract and differ between tokens.
Amounts are handled as integer minor units with the contract's decimals, never as floating point. A decimals assumption produces an amount wrong by orders of magnitude, which is the worst possible rounding error.
A jetton transfer requires native TON for fees, even when the payment itself is entirely in USDT.
A customer holding USDT and no TON cannot pay. The checkout detects this and explains it, because the wallet's own error message is opaque and the customer concludes your storefront is broken.
A confirmed transfer is irreversible, with no chargeback and no arbiter.
Refunds are a new payment you send, executed as a business process. The storefront copy must say so rather than implying a card-like refund right.
How it fails, and what happens when it does
The customer has USDT but no TON for fees.
By far the most common payment failure with jettons. It is detected before checkout and explained plainly, since neither the wallet nor the chain will explain it for you.
A transfer arrives for the right amount with no usable reference.
Matched on amount and destination where unambiguous, escalated to a human where not. Crediting an unidentifiable payment to the nearest pending order gives the wrong customer someone else's goods.
A different jetton is sent to the same address.
The watcher matches on jetton master address as well as amount. Treating any incoming transfer as the expected one credits an order for a token with no value.
A customer sends slightly less than quoted because of a wallet-side fee assumption.
A small tolerance band is defined explicitly rather than left to chance, and anything outside it goes to review. Silent acceptance of underpayment is a policy decision that should be made deliberately.
Availability in the UAE and the wider GCC
Global
Available to anyone with a TON wallet holding USDT. No onboarding, no merchant account and no per-country enablement.
United Arab Emirates
Widely used among Dubai crypto businesses. Accepting stablecoin payments may be a regulated activity depending on what you are selling; VARA is the relevant authority.
Consumer commerce
Practical only where your customers already hold USDT on TON. It is an excellent rail for a crypto audience and a wall for a general one.
Refund-sensitive categories
Irreversibility is a poor fit where refunds are frequent and expected. Card rails exist partly for this and it is a legitimate reason to choose one.
When not to use this integration
- Your customers do not hold USDT on TON. The rail is excellent for a crypto audience and unusable for a general one.
- Refunds are frequent in your category. Irreversibility makes every refund a manual outbound payment.
- You need settlement into a bank account. That is a separate off-ramp and a separate regulatory question.
- You are selling digital goods to a Telegram audience. Stars are simpler for both sides and need no wallet.
What it runs on
| Component | Version | Why |
|---|---|---|
| Cloudflare Workers | current | Quote generation, jetton wallet resolution and transfer watching. |
| Cloudflare D1 | current | Expected transfers, tolerance bands and the review queue. |
| TON API | v2 | Chain reads for jetton wallets and transfer history. |
| TypeScript | 5.9 | Strict mode, with amounts as integer minor units throughout. |
Questions that come up during scoping
Why does USDT convert better than native TON?
Because the quoted amount means the same thing when the customer presses send. Quoting in a volatile asset makes a purchase feel like a bet on timing, and abandonment rises with visible movement between quote and payment.
Why can a customer with plenty of USDT not pay?
Because a jetton transfer needs native TON for fees. It is the most common jetton payment failure and neither the wallet nor the chain explains it usefully, so the checkout detects the condition and explains it before the customer concludes your storefront is broken.
How are amounts handled safely?
As integer minor units using the contract's own decimals, never as floating point. A decimals assumption produces an amount wrong by orders of magnitude, which is not a rounding error so much as a different number.
Can we refund a USDT payment?
Only by sending a new payment. The original is irreversible on confirmation and there is no arbiter, so refunds are a business process rather than an API call. The storefront copy should say that rather than implying a card-like right.
What if someone sends a different token to our address?
The watcher matches on the jetton master address as well as the amount, so it is not credited. Treating any incoming transfer as the expected one is how an order gets fulfilled for a token worth nothing.
What about an underpayment by a few cents?
A tolerance band is defined explicitly and anything outside it goes to human review. Accepting underpayment silently is a reasonable policy and should be a decision somebody made rather than a default nobody noticed.
Related reading
Watching for the transfer and setting confirmation depth is covered by the TON API integration.
For digital goods to a non-crypto audience, the simpler rail is the Telegram Stars integration.
The product this payment rail usually sits behind is the Mini App storefront.
The wallet connection that precedes any transfer is TON Connect.