Pay with USDT
Let a customer pay a Lightning receive with USDT on Tron. One public mutation gives them a deposit address, and the receive settles like any other.
A customer who holds USDT on Tron can pay a receive without a Lightning wallet. public.create_swap gives them a Tron deposit address and an exact amount. When the USDT arrives, it's swapped and pays the receive's Lightning invoice. You still get bitcoin in your wallet, and the receive completes with the usual webhooks.
The mutation needs no API key, because the customer is the one paying. All it needs is the receive's ID.
Rules
- Tron USDT only for now. Send
source_chain: "tron"andsource_asset: "USDT". - Live BTC receives only. The receive must be on a BTC wallet in a live environment, still
PENDING, and not expired. - Exact amount. The customer sends exactly
amount_in, beforeexpires_at. Their wallet adds the Tron network fee on top. - Refunds. If the USDT arrives late or short, it goes back to
refund_address, a Tron address the customer owns.
Start a swap
public.create_swap(input: CreateSwapInput) → Swap
| Field | Type | Required | Notes |
|---|---|---|---|
transaction_id | UUID | yes | The receive to pay |
source_chain | string | yes | "tron" |
source_asset | string | yes | "USDT" |
refund_address | string | yes | The customer's Tron address, for late or short payments |
mutation CreateSwap {
public {
create_swap(input: {
transaction_id: "b2c4e6a8-1d3f-4b5a-9c7e-0f2a4c6e8b1d"
source_chain: "tron"
source_asset: "USDT"
refund_address: "TCustomerRefundAddress111111111111"
}) {
deposit_address
deposit_memo
amount_in
expires_at
}
}
}curl -X POST https://app.amboss.tech/graphql \
-H "Content-Type: application/json" \
-d '{
"query": "mutation($input: CreateSwapInput!) { public { create_swap(input: $input) { deposit_address deposit_memo amount_in expires_at } } }",
"variables": {
"input": {
"transaction_id": "b2c4e6a8-1d3f-4b5a-9c7e-0f2a4c6e8b1d",
"source_chain": "tron",
"source_asset": "USDT",
"refund_address": "TCustomerRefundAddress111111111111"
}
}
}'Example response:
{
"data": {
"public": {
"create_swap": {
"deposit_address": "TDepositAddress1111111111111111111",
"deposit_memo": null,
"amount_in": "20123456",
"expires_at": "2026-11-12T14:05:00.000Z"
}
}
}
}amount_in is in USDT's smallest unit. USDT on Tron has 6 decimals, so "20123456" is 20.123456 USDT. Show the customer deposit_address and the amount, and tell them to send before expires_at. If deposit_memo isn't null, they must add it to the transfer.
Calling it again with the same refund_address gives back the same address while it has more than a minute left. So a retry or a double click never shows the customer two addresses.
Limits
- 10 calls a minute from one IP address.
- 5 new deposit addresses a minute for one receive. Calls that give back an open address don't count.
Over a limit, the call fails with TOO_MANY_REQUESTS. Wait a minute and try again.
Errors
extensions.code | Meaning |
|---|---|
BAD_REQUEST | An input is missing or invalid, or the chain and asset aren't tron and USDT. |
NOT_FOUND | No payable receive with this ID: it doesn't exist, isn't PENDING, has expired, or isn't on a live BTC wallet. |
CONFLICT | A USDT payment for this receive is already on its way, so don't start another. Or another call is creating an address right now: try again in a moment. |
TOO_MANY_REQUESTS | Over a limit. |
Next steps
Lightning Addresses
Claim a Lightning Address like [email protected] so anyone can pay you from a Lightning wallet. Payments land in your wallet as normal receives.
Send Payments
Pay outbound Lightning invoices, Lightning Addresses, and saved payment destinations programmatically from any Amboss wallet.