How to Accept USDT on TRON Through an API
Connect your TRON wallet to a hosted checkout, create an exact USDT payment and fulfil orders after a verified webhook.
How the payment moves
Your customer sends USDT on TRON directly to your wallet. Your backend creates a hosted payment page through Dedyx. Dedyx checks the transfer and sends a signed PAID event; your application decides how to fulfil the order.
The integration is Create → Pay → Verify → Webhook. An open checkout or a screenshot is not payment confirmation.
1. Prepare your account and wallet
Request beta access with your project, payment use case, daily volume estimate and integration contact. Save the API key and separate rotation secret on your server. Check your beta dates, total and daily quotas through GET /api/v1/merchant/limits.
Use a TRON address that you control. Do not submit a private key, seed phrase or exchange login to Dedyx. The customer’s wallet must support USDT TRC-20 and cover its own TRON network fee.
2. Configure your webhook first
curl -X PUT https://api.dedyx.com/api/v1/merchant/webhook \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://your-company.example/webhooks/dedyx"}'Use a public HTTPS endpoint on port 443. Store the full signing_key and key_id from the first response securely; the secret is shown once. The receiver must verify the raw body before parsing JSON and must handle duplicates. See the webhook contract.
3. Create and save the order
curl -X POST https://api.dedyx.com/api/v1/payments \
-H "X-API-Key: YOUR_API_KEY" \
-H "Idempotency-Key: order-1024-v1" \
-H "Content-Type: application/json" \
-d '{"merchant_wallet":"YOUR_TRON_ADDRESS","amount":"49.00","description":"Order #1024"}'Persist the request fields and idempotency key before sending. Save payment_id, expected_amount and payment_url against your own order. On timeout, repeat the same request with the same key; do not generate a new key for the retry. The default replay retention is 24 hours. After retention or an uncertain final result, reconcile before creating another order.
4. Give the customer the payment page
Redirect to the returned payment_url. Add ?lang=ru if you want an explicit Russian checkout; otherwise the page chooses a supported language. The customer sends exactly the displayed USDT amount using TRON (TRC-20), before the expiry shown on the page. Network fees are separate from the amount the receiving address must receive.
Concurrent orders on one wallet address must have different exact amounts. An unfinished PENDING/CHECKING/REVIEW order reserves its amount on that address. Each order needs one full exact transfer; partial transfers are not added together. Reusing an amount carries the attribution limits explained in Payments.
5. Verify and fulfil once
Verify X-Dedyx-Signature, timestamp and key ID against the original request bytes, then compare the event header ID with payload.event_id. Match payment_id to your stored order, require PAID and compare the expected amount exactly. If needed, read authenticated payment details to verify the saved wallet and transfer identifiers.
Atomically save the event ID with the order’s business action in your database. Repeated deliveries must return 2xx without repeating fulfilment. If fulfilment calls another service, enqueue an idempotent delivery job in the same transaction rather than calling the service inside the transaction. See the PostgreSQL transaction example.
Handle exceptions before going live
Too little, too much or several partial transfers do not count as one exact payment. Expired and canceled orders do not automatically become PAID when a transfer is discovered. A timely transfer discovered after terminal expiry needs reconciliation. Refunds and customer support stay with the merchant.
Test timeouts, 429/503, receiver downtime, duplicates, expiry/cancel and restoration after restart. Error handling and FAQ describe these cases.