# 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](https://stons.io/docs/invoices.md#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](https://stons.io/docs/authentication.md#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](https://stons.io/docs/invoices.md#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

- **`balance` is 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.
- **`unconfirmed` is 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 of `balance` when it is confirmed — see [statuses](https://stons.io/docs/invoices.md#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](https://stons.io/docs/invoices.md#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_assets` instead.

## 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

```sh
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:

```json
{
  "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"
  }
}
```
