EPTRC (Easy Payment TRC) is a lightweight TRC20-USDT payment gateway.
Merchant systems can integrate USDT collection through simple HTTP APIs + Webhook callbacks.
bun install
bun run devPORT=3000
API_KEY=it.is.very.secret
WEBHOOK_KEY=it.is.webhook.secret
DB_FILE_NAME=eptrc.sqlite
TRON_NETWORK=nilePORT: service port, default3000.API_KEY: auth key for business endpoints (X-API-KEY).WEBHOOK_KEY: auth key used for webhook delivery; falls back toAPI_KEYif unset.DB_FILE_NAME: SQLite database file name, defaulteptrc.sqlite.TRON_NETWORK:nilefor testnet,mainfor mainnet.
bun run dev: start local development server (hot reload)bun run lint: run oxlintbun run lint:fix: run oxlint with auto fixesbun run db:generate: generate Drizzle migrations from schema changesbun run db:check: verify schema and migrations are synchronizedbun run db:push: push Drizzle schema to the databasebun run build:bun: build Bun runtime version todist/bun run build:linux-x64: build Linux x64 executablebun run build:windows-x64: build Windows x64 executablebun run build:darwin-x64: build macOS Intel x64 executablebun run build:darwin-arm64: build macOS Apple Silicon executable
GET /does not require authentication.- Other endpoints require
X-API-KEYin request headers.
- Call
POST /paymentSession/createto create a payment session. - Show the returned
addressand ask the user to transfer funds. - Receive Webhooks (
payment.session.paidorpayment.session.timeout). - Call
POST /paymentSession/detailfor reconciliation when needed. - Periodically call
POST /wallet/collectto collect paid wallet balances.
- All
amountfields use integer strings in on-chain minimal units. - TRC20-USDT uses
decimals = 6. - Conversion example:
1000000 = 1.000000 USDT.
- Business succeeded: return
HTTP 200. - Business failed: return
HTTP 4xxorHTTP 5xx.
GET /
Response example (HTTP 200):
{
"version": "1.0.0",
"tronGridBaseUrl": "https://nile.trongrid.io",
"contractAddress": "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
}POST /paymentSession/create
Request body:
{
"metadata": "{\"orderId\":\"order.123\",\"userId\":\"user.456\"}",
"notifyUrl": "https://api.merchant-system.com/eptrcNotify"
}notifyUrl: required callback URL for payment results.metadata: optional; any string, passed through unchanged in webhook payload.
Response example (HTTP 200):
{
"paymentSessionId": "019bf34f-9bec-7000-9b43-2ff5f5b0427d",
"address": "TTU6hE7tn9UX9XxcbQ3fZMZY3SH4GfMYZy",
"expiresAt": 1577934245000
}POST /paymentSession/detail
Request body:
{
"paymentSessionId": "019bf34f-9bec-7000-9b43-2ff5f5b0427d"
}Use this endpoint to query session status, paid amount, blockchain tx id, and collection state.
Response example (HTTP 200):
{
"id": "019bf34f-9bec-7000-9b43-2ff5f5b0427d",
"metadata": "{\"orderId\":\"order.123\",\"userId\":\"user.456\"}",
"amount": "1000000",
"notifyUrl": "https://api.merchant-system.com/eptrcNotify",
"address": "TTU6hE7tn9UX9XxcbQ3fZMZY3SH4GfMYZy",
"status": "paid",
"collected": 0,
"blockchainTxId": "2a6a...",
"paidAt": 1577934200000,
"expiresAt": 1577934245000
}POST /wallet/collect
Request body:
{
"toAddress": "TRx...target.address",
"feePayerPrivateKey": "your.fee.payer.private.key"
}toAddress: destination address for collection.feePayerPrivateKey: private key of the wallet paying TRX network fees.- Ensure this key's address has enough TRX.
- Never expose this key in frontend code, logs, or public channels.
Response example (HTTP 200):
{
"collectResults": [
{
"address": "Txxx...",
"status": "collected",
"amount": "1000000",
"txId": "2a6a..."
},
{
"address": "Tyyy...",
"status": "no.balance"
},
{
"address": "Tzzz...",
"status": "error",
"error": "collect.failed"
}
]
}When session status changes, EPTRC sends a POST request to notifyUrl.
Request headers:
X-API-KEY: <WEBHOOK_KEY>
Content-Type: application/json
User-Agent: EPTRC/<version>Merchant response requirements:
- Return
HTTP 200so EPTRC marks delivery as successful. - Non-
200responses are treated as failures and retried (max retries: 10). - Verify
X-API-KEYequals configuredWEBHOOK_KEY(or fallbackAPI_KEYif unset).
Event types:
payment.session.paidpayment.session.timeout
payment.session.paid example:
{
"event": "payment.session.paid",
"data": {
"paymentSessionId": "019bf34f-9bec-7000-9b43-2ff5f5b0427d",
"metadata": "{\"orderId\":\"order.123\",\"userId\":\"user.456\"}",
"amount": "1000000"
}
}payment.session.timeout example:
{
"event": "payment.session.timeout",
"data": {
"paymentSessionId": "019bf34f-9bec-7000-9b43-2ff5f5b0427d",
"metadata": "{\"orderId\":\"order.123\",\"userId\":\"user.456\"}"
}
}If this project helps you, you can support via this TRON address:
TTU6hE7tn9UX9XxcbQ3fZMZY3SH4GfMYZy