#Introduction
cryptoinfra is custodial wallet infrastructure on TRON. You bring your users; the platform gives each of them a Static Wallet Address, watches it, credits confirmed deposits to a double-entry ledger, and executes payouts on their behalf.
You never handle a private key, and you never write chain-specific code. You call one REST API — https://api.cryptoinfra.build — with your merchant key, and the platform speaks the chain underneath. GET /v1/assets is the live list of what can be received and sent — today TRX, USDT (TRC20) and USDC (TRC20).
Start here In a hurry? The Quickstart is six copy-paste calls from a new user to a paid-out balance, with the five mistakes everyone makes. The rest of this page is the model behind them.
#The happy path
POST /v1/users → a static wallet address
GET /v1/users/{id}/balances
POST /v1/withdrawals → payout, with an idempotency keyCreate the user.
POST /v1/userswith your ownexternal_user_id— a number of 5 to 10 digits. You get one Static Wallet Address back — a permanent TRON address that never expires and never rotates, so you can store and display it once. The call is idempotent onexternal_user_id: replaying it returns the same user and the same address, still201.Show the static address; wait for the deposit. When your user sends funds, the platform detects the transaction, waits for the chain's confirmation threshold, credits the balance in full (deposits are free), and fires a
deposit.creditedwebhook.Read the balance.
GET /v1/users/{externalId}/balancesreturns per-asset spendable balances. Assets with no activity are simply absent from the response.Pay out.
POST /v1/withdrawalsholdsamount + fee + platform_feefrom the user's balance and queues the payout.feeis the live network cost of the send, gas included (quote it first withGET /v1/withdrawal-fee-quote, which also says whether the figure is live);platform_feeis the flat platform fee.amountis what the recipient receives. You get202 Acceptedback; the outcome arrives aswithdrawal.confirmedorwithdrawal.failed— and the failure path refunds the hold automatically.
Preview the exact cost of step 4 before you commit to it with GET /v1/withdrawal-fee-quote.
#What "custodial" means here, precisely
Three facts follow from the custodial model, and every integration decision comes back to one of them.
Keys are ours, balances are yours. The platform derives and holds the keys for every address it hands out. Your API key authenticates you, the merchant — never your end user. A user identifier is a number you choose (external_user_id, 5 to 10 digits); it carries no authority of its own. Never ship the API key to a browser or a mobile app.
Balances are ledger rows, not chain state. A user's balance is a double-entry ledger position, not a getBalance call. It is credited when a deposit clears confirmations and debited the moment a payout is requested, not when it confirms. That is deliberate: the balance you read is always spendable and always net of holds, so it can read lower than the chain while an operation is in flight, and never higher.
Every movement of money is on-chain. A payout — to one of your own users or to any address outside the platform — is a POST /v1/withdrawals, priced with our fee and the network's gas. There is no off-chain book transfer between accounts.
#Your account is live the moment you sign up
You create your account yourself at the dashboard — company, email, password and a Telegram username. There is no approval step: the account is active from the first minute. The one thing it waits on is your email. Until the address is verified you cannot sign in, and you cannot generate or see an API key (403 email_unverified); the link is in your inbox, and the sign-in page can send a fresh one. Verify it, sign in, and the dashboard is yours: generate your key, register webhooks, invite teammates, use the sandbox — and the API and every money feature are open.
Signup is open, not unguarded. Use a mailbox you will keep — disposable addresses are refused (400 email_disposable) — and, when the page shows one, complete the bot check before you submit (400 bot_check_failed otherwise). We keep where a signup and each sign-in came from, and we look at accounts that share a network, a Telegram username, a company e-mail domain, a payout address or their customers with another merchant; such a link, or a day of earnings far out of line with your own history, can hold a profit withdrawal for a look — the request says so — but never closes an account on its own.
#Webhooks are hints; the poll is truth
This is the single most important operational rule in the API, and it is worth internalising before you write any code.
And some flows have no webhook at all. Swaps and exchanges emit nothing — there is no swap.completed and no exchange.completed. Code that waits for one waits forever. See Webhooks for the complete list and what to poll instead.
#What else is in the API
Beyond the wallet core, the same key and the same conventions reach every flow. Each has a short guide that walks it once, in order:
- Payouts — quote, send, and learn the outcome.
- Swaps and exchange — trade between assets a user holds, or sell one and pay any of thousands of other coins out to an external address.
- Cards, end to end — issue crypto debit cards to your users, funded from their own balance. Cards settle in USDT; a card is issued funded.
- Developer — register webhook endpoints and read your own request log.
#Conventions at a glance
| Convention | What to expect |
|---|---|
| Base URL | https://api.cryptoinfra.build |
| Auth | Authorization: Bearer ck_… — see Authentication |
| Casing | snake_case everywhere, in both directions |
| Money | decimal string + exact *_base integer string — see Money and amounts |
| Timestamps | RFC 3339 with an offset; date filters accept a bare IST calendar day |
| Errors | { "error": "code", "message": "…" } — see Errors |
| Mutations | carry an idempotency_key — see Idempotency |
| Contract | OpenAPI 1.0.0, 68 operations, 56 schemas, 9 webhook events |
Every page of this reference is generated from that OpenAPI contract, so it cannot drift from the running service. Every page is also available as raw Markdown at /md/{slug}, and the whole site as one file at /llms-full.txt — see AI integration.