Watch addresses, get UTXOs and balances
Step by step: watch deposit addresses, list UTXOs and balances, check spends and sweep with exact inputs.
# Watch addresses, get UTXOs and balances
A platform that takes deposits needs to know what each address holds and then move it. You will watch your deposit addresses, list their UTXOs and balances, confirm the outputs are unspent and sweep them into one wallet. Signing is covered in [Send a transaction](https://docs.rarebl.com/guides/send-a-transaction); this guide is about finding and choosing the funds.
## Before you start
- The deposit addresses and the chain (`btc`, `ltc`, `bch`, `dash`, `eth` or `tron`).
- On **BTC, LTC and BCH** an address needs a **watch** before the API can list its UTXOs or an exact balance. **DASH** works without one (it uses its node index). ETH and TRON have no UTXOs: skip to step 6.
- A hot-wallet address to sweep into, and the signing key for the deposit addresses ([Sign locally with the SDKs](https://docs.rarebl.com/guides/sign-locally)).
## Step 1 — Watch the addresses
Start a watch for up to 100 addresses per call. The API runs a UTXO-set bootstrap, then follows new blocks and the mempool.
```bash cURL
curl -X POST https://api.rarebl.com/open/address/watch -H "Content-Type: application/json" \
-d '{"chain":"btc","addresses":["bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q"]}'
```
```js JavaScript
const res = await rarebl.watch('btc', ['bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q']); // waits until active
```
```python Python
res = c.watch("btc", ["bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q"])
```
```php PHP
$res = $c->watch('btc', ['bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q']);
```
```bash Shell
rarebl watch --chain btc bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q
```
**You should see** each address as `pending`, then `active` once its bootstrap is done (example values).
```json
{ "watches": [ { "address": "bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q", "status": "pending", "since": "2026-11-15T01:12:07Z" } ] }
```
The watch class allows 30 calls per minute and 2,000 addresses per day. Watches expire after 90 days without a query or webhook; any read renews them. An `address.activity` [webhook](https://docs.rarebl.com/guides/webhooks) or a WebSocket `address:*` channel on BTC, LTC or BCH starts the watch for you.
## Step 2 — Wait until the watch is active
Until a watch is `active`, [Address UTXOs](https://docs.rarebl.com/api/address/utxos) answers `API409` with the reason `not_watched`. Poll every few seconds; how long the bootstrap takes depends on the chain.
```bash cURL
curl "https://api.rarebl.com/open/address/utxos?chain=btc&address=bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q"
```
**You should see** this reply while the address is not watched (or not active yet), and a normal UTXO list once it is:
```json
{ "status": 0, "code": "API409", "message": "address is not watched yet: POST address/watch first",
"data": { "reason": "not_watched", "watch": { "chain": "btc", "address": "bc1q7dszvzdj8lk8dd4ssad94m0t2acunaf48j455q", "endpoint": "address/watch" } }, "go": null, "meta": { "requestid": "0123456789abcdef", "notices": [] } }
```
## Step 3 — List UTXOs and the balance
Once active (or straight away on DASH), list what the address holds. Use `minConf` to ignore unconfirmed deposits.
```bash cURL
curl "https://api.rarebl.com/open/address/utxos?chain=dash&address=XnL1FvTKqe6aWfB8NrvgbUMuWCEA3dNxfF&minConf=1"
```
```js JavaScript
const { utxos, balance } = await rarebl.utxos('dash', 'XnL1FvTKqe6aWfB8NrvgbUMuWCEA3dNxfF', 1);
```
```python Python
r = c.utxos("dash", "XnL1FvTKqe6aWfB8NrvgbUMuWCEA3dNxfF", min_conf=1)
```
```php PHP
$r = $c->utxos('dash', 'XnL1FvTKqe6aWfB8NrvgbUMuWCEA3dNxfF', 1);
```
```bash Shell
rarebl utxos --chain dash XnL1FvTKqe6aWfB8NrvgbUMuWCEA3dNxfF --min-conf 1
```
**You should see** the UTXOs plus the total (a real Dash reply):
```json
{ "utxos": [ { "txid": "1fa1b672aa5ef13127ede15aeef61c5fe3ec8565031cd826f65e6a332baefb9c", "vout": 1, "value": "4.23877346", "valueSats": 423877346,
"height": 2572425, "confirmations": 2, "scriptPubKey": "76a9147fb0a45f00c25ff1cb67753221326c7c420b8b2388ac" } ],
"balance": "4.23877346", "balanceSats": 423877346 }
```
While an address is watched and active, [Address](https://docs.rarebl.com/api/address/balance) also returns an exact `balance` on BTC, LTC and BCH (`balanceStatus: "exact"`). Compare amounts as decimal strings or with a big-number type, never as floats.
## Step 4 — Check the outputs are unspent
Before you spend, [Output spend status](https://docs.rarebl.com/api/tx/outspends) says whether an output is spent, by what, and whether that spend is still in the mempool.
```bash cURL
curl "https://api.rarebl.com/open/tx/outspends?chain=btc&id=9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db"
```
**You should see** one entry per output: `spent: false` is spendable.
```json
{ "outputs": [ { "n": 0, "spent": false, "spentBy": null, "inMempool": false }, { "n": 1, "spent": true, "spentBy": null, "inMempool": false } ] }
```
## Step 5 — Sweep with exact inputs
Build a transaction that spends exactly the UTXOs you listed, to your hot wallet, with `amount: "max"` (everything less the fee). UTXO chains allow one `to` per transaction, so build one transaction per destination.
```bash cURL
curl -X POST https://api.rarebl.com/open/tx/build -H "Content-Type: application/json" -d '{
"chain": "dash",
"inputs": [{"txid": "1fa1b672aa5ef13127ede15aeef61c5fe3ec8565031cd826f65e6a332baefb9c", "vout": 1}],
"to": [{"address": "XiM9Afap6UEb5LDkcWrg2YyA28hifkZZKM", "amount": "max"}],
"priority": "standard"
}'
```
```js JavaScript
const reply = await rarebl.build({
chain: 'dash',
inputs: [{ txid: '1fa1b672aa5ef13127ede15aeef61c5fe3ec8565031cd826f65e6a332baefb9c', vout: 1 }],
to: [{ address: 'XiM9Afap6UEb5LDkcWrg2YyA28hifkZZKM', amount: 'max' }],
priority: 'standard',
});
```
```python Python
reply = c.build({
"chain": "dash",
"inputs": [{"txid": "1fa1b672aa5ef13127ede15aeef61c5fe3ec8565031cd826f65e6a332baefb9c", "vout": 1}],
"to": [{"address": "XiM9Afap6UEb5LDkcWrg2YyA28hifkZZKM", "amount": "max"}],
"priority": "standard",
})
```
```php PHP
$reply = $c->build([
'chain' => 'dash',
'inputs' => [['txid' => '1fa1b672aa5ef13127ede15aeef61c5fe3ec8565031cd826f65e6a332baefb9c', 'vout' => 1]],
'to' => [['address' => 'XiM9Afap6UEb5LDkcWrg2YyA28hifkZZKM', 'amount' => 'max']],
'priority' => 'standard',
]);
```
**You should see** the same reply as in [Send a transaction](https://docs.rarebl.com/guides/send-a-transaction): `unsigned` and `toSign`, with a single output that has no change. Verify, sign, assemble and broadcast it with the steps there. Inputs are verified unspent with the node, so a stale input fails with `inputs_spent` or `inputs_unknown`.
For a **payout** from a wallet use `from` instead of `inputs` and let the API choose the UTXOs; set `change` to the address that should receive the change (the default is the first `from` address).
Choose the fee:
| Option | When |
| --- | --- |
| `priority: "slow"`, `"standard"` or `"fast"` | Let the API pick from its estimator (targets of 24, 6 and 2 blocks on Bitcoin). |
| `feeRate: "12"` | A fixed rate in sat/vB. |
| `rbf: true` (the default on BTC and LTC) | Allows a later replacement if the fee turns out too low: [Stuck transactions](https://docs.rarebl.com/guides/stuck-transactions). |
Use [Recommended fees](https://docs.rarebl.com/api/fees/recommended) to see current levels and [Estimate](https://docs.rarebl.com/api/tx/estimate) to price a specific transaction. Many small inputs make a large transaction: consolidate when fees are low.
## Step 6 — ETH and TRON deposits
There are no UTXOs. Read balances with [Address](https://docs.rarebl.com/api/address/balance) and [Address tokens](https://docs.rarebl.com/api/address/tokens), the nonce with [Address nonce](https://docs.rarebl.com/api/address/nonce) (ETH) or the energy and bandwidth with [Address resources](https://docs.rarebl.com/api/address/resources) (TRON), then build a transfer from the deposit address (that address's key signs).
```bash cURL
curl "https://api.rarebl.com/open/address/resources?chain=tron&address=TNPeeaaFB7K9cmo4uQpcU32zGK8G1NYqeL"
```
**You should see** the account's resources (a real TRON reply).
```json
{ "energy": { "limit": 0, "used": 0, "available": 0 }, "bandwidth": { "free": 600, "staked": 0, "used": 158, "available": 442 }, "frozen": [] }
```
A deposit address that holds only a token needs ETH (or TRX) to pay for the sweep: send the gas first, wait for it to confirm, then sweep. Token transfers: [Sign locally with the SDKs](https://docs.rarebl.com/guides/sign-locally).
## Common errors
| Reply | What it means | What to do |
| --- | --- | --- |
| `API409` `not_watched` | BTC, LTC or BCH: the address is not watched and active. | Start a watch (step 1) and poll until `active`. |
| `API400` on `address/utxos` | ETH and TRON have no UTXOs, or the address is malformed. | Use balances and tokens instead. |
| `API422` `inputs_spent`, `inputs_unknown` | An input was spent, or the node does not know it. | Re-list the UTXOs and build again. |
| `API422` `insufficient_funds`, `dust_output` | The inputs cannot cover the amount plus the fee, or an output is too small. | Add inputs, or sweep with `amount: "max"`. |
| `API429` | Watch: 30 per minute and 2,000 addresses per day. Compute: 2 per second. | Wait `Retry-After`; watch only what you need. |
## Next steps
- Sign and send the sweep: [Send a transaction](https://docs.rarebl.com/guides/send-a-transaction) or [Sign locally with the SDKs](https://docs.rarebl.com/guides/sign-locally).
- Be told about deposits instead of polling: [Webhooks](https://docs.rarebl.com/guides/webhooks).
- Confirm one deposit: [Track a deposit until it confirms](https://docs.rarebl.com/guides/track-a-deposit).
- A sweep that does not confirm: [Stuck transactions](https://docs.rarebl.com/guides/stuck-transactions).