Перейти до вмісту
CoinsSendРозробникам
Практичні сценарії

Accept USDT TRC-20 payments with the API

Відкрити MarkdownПідключити агента

Цей контент ще не доступний вашою мовою.

Use this recipe when your website sells a product or service for a known order amount and you want customers to pay in USDT on TRON. Your backend creates a CoinsSend invoice, the buyer follows its checkout URL, and your server confirms payment before fulfilling the order.

For repeat customer balance top-ups, use reusable deposit addresses instead.

  • A CoinsSend merchant account, Merchant ID, and API key.
  • A backend that stores orders and payment identifiers. Keep the API key there.
  • An HTTPS callback configured in your merchant settings and a webhook receiver that verifies signatures.

The complete request contract is in Invoices. PHP, Node.js, and Python examples provide the signed request implementation.

Fetch the public catalog before presenting payment choices:

Terminal window
curl --fail --show-error https://api.coinssend.com/v1/coins-and-fee
curl --fail --show-error https://api.coinssend.com/v1/get-coin-rate

Match the coin/network pair in both responses. The API values for USDT TRC-20 are coin: "usdt" and network: "tron". TRC20 is a display label, not the network code to send. Check current deposit availability; see coin selection and operation flags.

Display USDT · TRON (TRC-20) together. USDT sent over Ethereum is a different network choice, even though the token has the same name.

Send the following body from your backend to POST /v1/invoices, with the Merchant and Sign headers described in Authentication:

{
"order_id": "shop-order-1042",
"amount": "25.00",
"allowed_coins": ["usdt"],
"coin": "usdt",
"network": "tron",
"success_url": "https://shop.example/orders/1042",
"cancel_url": "https://shop.example/checkout"
}

amount is the invoice price in USD, not a request to collect exactly 25 USDT. The checkout calculates the crypto amount using the applicable rate and fee settings.

allowed_coins restricts coins. coin and network preselect the payment option; they are not a documented network allowlist. If your order policy requires a specific network, reconcile the actual payment pair before fulfillment.

Store data.id, data.code, data.order_id, and data.url against your local order, then send the buyer to data.url. Reuse that checkout link when the buyer returns to the same order.

The order ID must be unique per merchant. A duplicate returns 409; it does not replay the first response. After a timeout, reconcile the first attempt before creating another invoice.

A visit to success_url is not proof of payment. Verify the incoming webhook using X-Signature and the unchanged raw request body, then handle invoice.paid for the stored invoice and order.

Your fulfillment transaction should:

  1. Match the invoice ID and order ID to your stored order.
  2. Reconcile the signed status, requested amount, actual paid amount, and payment pair.
  3. Mark the local order paid and schedule fulfillment exactly once.
  4. Record duplicate deliveries without issuing the product again.

Use a database uniqueness rule or an equivalent atomic transition for the local fulfillment record. X-Idempotency-Key is not guaranteed on every notification; your invoice/order identifiers must also protect against duplicate fulfillment.

SituationYour application’s response
The buyer returns before confirmationShow “Awaiting payment confirmation”; keep the order unfulfilled.
Invoice lookup reports partialShow the remaining amount from the current checkout state. Partial payment is not a paid order.
A verified invoice.paid arrivesFulfill once after reconciling the order and payment.
A verified invoice.expired arrivesClose the checkout attempt as expired; do not treat any partial amount as a completed order.
The same callback arrives againAcknowledge the already recorded event without repeating fulfillment.
The callback or creation result is uncertainReconcile stored identifiers and the invoice lookup; avoid blindly retrying a write.

CoinsSend does not document a separate webhook for every intermediate invoice status. Use the current lookup response when your UI needs progress information.