Product
One payment layer that brings on-chain money into your books
This page explains how it works — how an order moves, how callbacks are verified, where the money goes, and who catches it when something breaks. Read it and you'll know whether it fits your system.
The premise
Why cross-border sellers start taking USDT
No bank in the loop
The worst part of cross-border collection isn't the fee, it's whether the money arrives at all: rejected account openings, frozen accounts, returned transfers. A stablecoin transfer doesn't ask about your bank or about the relations between two countries.
No FX loss, no intermediary bank
USDT tracks the dollar, so you collect, book and settle in one unit. You drop the conversion spread and the correspondent fees — and those "we're $17 short" moments at reconciliation.
24/7, in minutes
Weekends, holidays and the middle of the night collect as usual. On-chain confirmation is measured in minutes, not in "T+2 business days".
Programmable
Every payment carries a transaction hash and a confirmation count, so you can reconcile and ship automatically — something traditional rails simply can't give you.
The core
The full life of an order
The state machine is the backbone of the whole system: only on-chain verification can push an order to Confirmed. The transaction hash a buyer sends back can only push it to Submitted. That line is what makes a forged receipt impossible.
⚠️ One rule for developers: never compare order states by numeric value (say, "status ≥ 3 means paid"). The codes carry no increasing semantics — a state added later will silently fool that check.
Coverage
Chains and tokens
Addresses and validation rules are normalized by chain type (chainType), so adding another chain of a type you already support needs no change to settlement logic.
One address per chain
A merchant uses a separate address on each chain and can enable or disable them individually; the checkout picks the address for whichever chain the buyer chooses.
Addresses normalized per chain
EVM addresses are lowercased, TRON keeps its case — so one address has exactly one stored form. Otherwise the same wallet is recorded twice and reconciliation never lines up.
Only the chains you enable
You tick the chains and tokens you want in the console. Chains you don't collect never appear at checkout, so a buyer can't pay into the wrong place.
Integration
Callbacks: signed, retried, queryable
Callbacks fail (your site restarts, the network hiccups, your code throws), so they must retry. And retrying means a duplicate may arrive, so they must be verifiable and idempotent.
Signature (against forgery)
Headers carry a timestamp and an HMAC-SHA256 signature computed over the timestamp plus the request body; the event type is in X-Pay-Event (for example pay.confirmed). A failed verification is dropped every time.
Retries (against lost orders)
Retried on a backoff: 5s → 30s → 2m → 10m → 30m → 1h → 2h → 6h. Return 2xx and we stop.
Idempotency (against double shipping)
Deduplicate on merchantOrderNo — on a repeat callback just return success and don't ship again.
Active queries (against passivity)
Don't trust callbacks alone: poll the query API against your open orders on a schedule. A missed callback tells you nothing; a query is you going to ask.
A real trap
Amounts take different forms on different endpoints: the Open API (server to server) takes a decimal string in token units (like "100" / "100.5"), while the checkout order endpoint takes an integer string in the smallest unit. They are the opposite of each other — copy the wrong one and you are off by 10^decimals. Trust Create order and Error codes.
Security
How the Open API defends itself
Keep the key server-side
An API KEY must never reach a browser — that hands every visitor the right to create orders as you. The front end uses the checkout link only.
Idempotent ordering
merchantOrderNo is the idempotency key: network timeouts, impatient double-clicks and callback retries never turn into two orders.
No secrets in logs
API KEYs, verification codes and SMTP passwords never get logged; a log line keeps the last four characters or a hash.
CORS narrowed by path
The Open API allows any Origin (it authenticates with a header key and sends no cookies, so there is no CSRF surface); every other endpoint adds no CORS header at all.
Architecture
Two sides, deployed apart: platform and merchant
The platform side runs operations (merchant approval, chains and tokens, risk rules, reconciliation); the merchant side runs the business (its own console, its own orders and ledger). The two deploy independently, on separate databases — one merchant's growth spurt never slows anyone else down.
Platform side
Configure chains and tokens, approve and manage merchants, and see platform-wide collection reports. It runs on the platform's own domain and database.
Merchant side
Each merchant's console: collection overview, collection addresses, payment orders, reports, settings. The data sits in its own database and is invisible across merchants.
Checkout
The page the buyer opens (/pay/cashier/m/{merchantNo}). Its own domain and deployment, deliberately kept out of search engines.
Cross-database references are IDs only
Plugins never JOIN across databases — those boundaries are hard, so one bad database doesn't drag the others down. The cost: anything that needs a join gets its own endpoint.
Want to run a real payment first?
Register a merchant, add one address on a chain you control, and you can take your first test payment within five minutes.