Balance
GET /v1/balance returns the money of the project: the balance of every asset it holds something in, and the same money in US dollars. Read it for your own dashboard, before asking for a withdrawal, and to reconcile your books against the service.
For a project the operator has switched to direct settlement this balance stays at zero, because the money of each payment is forwarded to the project's own wallet instead of being kept — see where the money goes. A zero there means the money has already arrived, not that nothing was paid.
Request
The request has no parameters and no body.
The answer carries an ETag, so a product that keeps the balance on a screen pays for one 304 while nothing has changed — see conditional reads.
Response
200 with balances, one row per asset, and total, those rows added up in dollars. An asset the project has no money in is not a row: a project that has never been paid gets an empty array and zero totals.
| Field | Type | Description |
|---|---|---|
balances[].asset |
string | Asset identifier, for example USDT_TRON — see assets |
balances[].network |
string | Identifier of the network of the asset, for example tron |
balances[].balance |
string | The balance in units of the asset, with all its decimals. Carries a minus sign when payouts have taken it below zero |
balances[].unconfirmed |
string | Payments seen on chain and not confirmed yet, in units of the asset. Not part of balance |
balances[].balance_usd |
string or null | balance at the exchange rate, in dollars and cents; null when the service has no fresh rate for the coin |
balances[].unconfirmed_usd |
string or null | unconfirmed at the same rate; null on the same condition |
total.balance_usd |
string | The balances of the assets that have a fresh rate, added up |
total.unconfirmed_usd |
string | The unconfirmed payments of those assets, added up |
total.unpriced_assets |
array of string | Assets with money but no fresh rate: they are in balances and not in the sums |
total.rates_observed_at |
string or null | When the oldest rate used in the sums was accepted; null when no rate is in them |
Rows come largest dollar value first, and the assets without a rate last.
Where the numbers come from
balanceis the ledger balance, the sum of the project's journal — never a stored number that something could forget to update. A payment adds to it when the transfer has enough confirmations; a payout and a withdrawal take from it. A correction is a reversing entry, so the balance always equals the history that produced it.unconfirmedis beside the balance, not in it. A transfer with too few confirmations can still vanish in a chain reorganisation, so it is not money yet. It becomes part ofbalancewhen it is confirmed — see statuses.- Amounts carry all the decimals of their asset, as everywhere in this API: count them in the string instead of building the number 6 into your code — see amounts.
- Dollars are informational. They are the amounts at the latest rate the service has accepted, cents rounded toward zero, so the total can differ from the sum of the rounded rows by a cent a row. An asset whose coin has no fresh rate is never valued at a stale one: it is named in
unpriced_assetsinstead.
Errors
| HTTP | error.code |
When |
|---|---|---|
| 401 | unauthorized |
The API key is missing or invalid |
| 403 | merchant_disabled |
The merchant is disabled |
| 429 | rate_limited |
The request limit is exceeded |
| 500 | internal_error |
An unhandled error of the service |
A merchant that has not been approved on review can read its balance.
Example
curl -s https://api.stons.io/v1/balance -H "X-Api-Key: $API_KEY"
200, a project with 100 USDT credited on TRON and 5 USDT still gathering confirmations:
{
"balances": [
{
"asset": "USDT_TRON",
"network": "tron",
"balance": "100.000000",
"unconfirmed": "5.000000",
"balance_usd": "99.96",
"unconfirmed_usd": "4.99"
}
],
"total": {
"balance_usd": "99.96",
"unconfirmed_usd": "4.99",
"unpriced_assets": [],
"rates_observed_at": "2026-10-04T17:31:05.531Z"
}
}