A withdrawal is a state machine, not a button
The interface should expose enough of this state to set expectations. “Pending” is acceptable for a short period; a permanent pending state without a reason or support route is not. The operator needs more detail than the user, including asset, destination, request identifier, attempts and final reference.
| State | What it means | What must not happen |
|---|---|---|
| Available | Balance can be requested under current rules | No transfer has been promised yet |
| Requested | Checks passed and one queue item exists | A repeated tap must not create another request |
| Review or queued | Request awaits an operator or worker | Balance cannot be spent twice |
| Broadcast | A transfer was submitted | Do not retry until chain status is known |
| Paid | The transfer is finalized and traceable | Do not refund the debit |
| Failed and refunded | No payment completed and balance was restored once | Do not run a second refund |
Name the asset before choosing automatic payout
Native TON, a Jetton, a project point and a manually distributed campaign token are different assets. They use different transfer formats, fee assumptions and operational controls. A generic amount field is dangerous when one worker could interpret every pending request as a native transfer.
Store the asset and payout mode on each request. Let the automatic worker select only supported automatic assets. Route manual project-token requests to an owner inbox where the operator can attach a transaction reference or deny and refund with a reason. Do not silently substitute one asset for another.
Reserve the balance atomically
When a valid request is created, reserve or debit the amount in the same transaction that inserts the queue record. If those actions are separate, two rapid requests can both see the old balance and spend it. Use a unique request key derived from the user action or generated server-side, then reject a repeated confirmation.
The ledger should preserve the reason for the debit. A failed request restores that exact debit through one refund event. Operators should not edit the total balance manually to “fix” a payout, because that destroys the audit trail and can hide a duplicate transfer.
- Atomic request and debit
- Unique request key
- Explicit asset
- Explicit payout mode
- Original ledger reference
- One refund reference
- Immutable final state
Validate destinations without pretending to own them
Validate that the destination is a syntactically acceptable address for the selected asset and network before queueing. Normalize formats where the official tooling supports it. Do not claim that format validation proves the user controls the wallet or that a custodial destination will accept every memo or token.
For a high-value or first withdrawal, a confirmation screen can show the normalized destination, asset, amount, estimated fee behavior and warning that blockchain transfers may be irreversible. Never ask users to reveal a seed phrase or private key.
- Network and asset named
- Address normalized
- Memo or comment rule stated
- Minimum and fee treatment visible
- Irreversibility warning
- No private-key collection
Fund the queue, not just the marketing balance
Compare the project wallet reserve with available user liability and already pending requests. A campaign may look funded while most value remains in unqualified points; the risk changes when those points become withdrawable. Alert before the automatic reserve falls below pending obligations.
Keep operational funds separate from estimates of future advertising or acquisition revenue. If the reserve is insufficient, stop creating new funded rewards or enter a disclosed maintenance state. Do not let the queue repeatedly fail and charge users through lost balances or hidden conditions.
Coverage ratio = liquid payout reserve ÷ (available withdrawable balances + pending requests)Design automatic and manual paths deliberately
| Mode | Use when | Required owner control |
|---|---|---|
| Automatic native payout | The platform supports the asset and project wallet is funded | Limits, reserve alerts, pause switch and key security |
| Automatic Jetton payout | A dedicated Jetton-aware implementation is tested | Correct master and wallet validation, decimals and fee reserve |
| Manual project-token payout | The owner distributes an external asset outside the native worker | Review inbox, proof reference, deny and refund actions |
| Campaign allocation only | No transfer is currently promised | Do not label points as withdrawable |
Prepare for the five incidents that will happen
- Insufficient wallet funds
Pause automatic dispatch, preserve requests and alert the owner.
- Ambiguous network response
Check chain state before retrying.
- Wrong or unsupported asset
Block before queueing and never substitute automatically.
- Compromised signing path
Disable payouts, rotate credentials and retain the ledger for reconciliation.
- Duplicate callback or worker retry
Idempotency returns the original request instead of paying again.
Run reconciliation as an operating habit
At a regular interval, compare opening reserve, deposits, confirmed outgoing transfers, fees and closing reserve. Separately reconcile user ledger debits with paid requests and refunds. A small unexplained difference is an incident, not rounding to ignore.
Monitor queue age, success rate, failures by reason, refunds, repeated destinations and coverage ratio. Publish expected processing behavior for users, and notify them through the bot when a material outage changes it. Reliable withdrawals are a product feature and a trust system.
Common questions
Can a Telegram Mini App send withdrawals automatically?
Yes, when the backend supports the exact asset, the project wallet is funded and signing, limits and queue controls are configured. The Mini App interface itself should not hold private keys.
Are native TON and Jetton withdrawals the same?
No. Jettons have their own master and wallet contracts, decimals and transfer flow. Never send a project-token amount through a native-asset worker.
What should happen when a withdrawal fails?
If no transfer completed, restore the reserved or debited user balance exactly once and mark the request with a final failure reason.
Should users pay a deposit to unlock withdrawal?
Only if it is a genuine, lawful and clearly disclosed product rule. Adding an unexpected deposit demand after rewards are earned is deceptive and should not be used as a payout control.
Sources and further reading
Technical and product claims were checked against these primary sources.