Track a deposit until it confirms
Step by step: poll tx/status until a transaction reaches your confirmation threshold, then verify the amount with tx/get.
# Track a deposit until it confirms
You have a transaction hash, for example from a customer who says "I sent it", and you want to know when it is safe to credit. You will poll [Transaction status](https://docs.rarebl.com/api/tx/status) until the transaction reaches your confirmation threshold, then confirm the amount and the address with [Transaction](https://docs.rarebl.com/api/tx/get).
## Before you start
- The `chain` the payment was sent on (`btc`, `ltc`, `bch`, `dash`, `eth` or `tron`) and the transaction hash (`id`).
- A confirmation threshold per chain. The reorg depths in [Data freshness](https://docs.rarebl.com/data-freshness) are 6 for BTC, LTC, BCH and DASH, 64 for ETH and 20 for TRON.
- Prefer being told instead of polling? Use a `tx.confirmations` [webhook](https://docs.rarebl.com/guides/webhooks) and skip to step 3.
## Step 1 — Ask for the status
```bash cURL
curl "https://api.rarebl.com/open/tx/status?chain=btc&id=9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db"
```
```js JavaScript
const url = 'https://api.rarebl.com/open/tx/status?chain=btc&id=9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db';
const body = await (await fetch(url)).json();
console.log(body.data.status, body.data.confirmations);
```
```python Python
import rarebl
c = rarebl.Rarebl()
data = c.status("btc", "9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db")
```
```bash Shell
rarebl status --chain btc 9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db
```
**You should see** a small reply with the status and the confirmation count.
```json
{
"status": 1, "code": "API200", "message": "success",
"data": { "hash": "9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db", "status": "success", "block": 975851, "confirmations": 20, "time": "2026-11-14T22:18:52Z" },
"go": null,
"meta": { "requestid": "0123456789abcdef", "notices": [] }
}
```
`data.status` is one of:
| `status` | Meaning | What to do |
| --- | --- | --- |
| `pending` | Seen in the mempool, not in a block. `block` and `time` are `null`, `confirmations` is 0. | Keep polling. |
| `success` | In a block. `confirmations` counts the blocks on top, including its own. | Credit once `confirmations` reaches your threshold. |
| `failed` | Included in a block but reverted (ETH and TRON). | Do not credit. |
## Step 2 — Poll until it confirms
Poll every few seconds, back off on errors, and stop at your threshold. Heads refresh about every 2 seconds, so polling faster gains nothing.
```js JavaScript
const THRESHOLD = { btc: 6, ltc: 6, bch: 6, dash: 6, eth: 64, tron: 20 };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function waitForConfirmations(chain, id) {
let delay = 4000;
for (;;) {
const res = await fetch(`https://api.rarebl.com/open/tx/status?chain=${chain}&id=${id}`);
const body = await res.json();
if (body.code === 'API200') {
const { status, confirmations } = body.data;
if (status === 'failed') return { ok: false, reason: 'reverted' };
if (status === 'success' && confirmations >= THRESHOLD[chain]) return { ok: true, confirmations };
delay = 4000;
} else if (body.code === 'API429') {
delay = Number(res.headers.get('Retry-After') ?? 1) * 1000;
} else if (body.code === 'API404') {
delay = 4000; // not seen by our node yet: keep waiting
} else if (body.code === 'API502' || body.code === 'API409') {
delay = Math.min(delay * 2, 30000); // node syncing or index pending: back off
} else {
throw new Error(`${body.code}: ${body.message}`); // API400 and friends: fix the request
}
await sleep(delay);
}
}
```
```python Python
import time
THRESHOLD = {"btc": 6, "ltc": 6, "bch": 6, "dash": 6, "eth": 64, "tron": 20}
def wait_for_confirmations(c, chain, txid):
delay = 4
while True:
try:
s = c.status(chain, txid)
if s["status"] == "failed":
return False
if s["status"] == "success" and s["confirmations"] >= THRESHOLD[chain]:
return True
delay = 4
except rarebl.ApiError as e:
if e.code == "API400":
raise # fix the request
delay = min(delay * 2, 30) # 404 not seen yet, 429, 502, 409: back off
time.sleep(delay)
```
**You should see** the function return once the threshold is reached (or at once with a failure for a reverted transaction).
## Step 3 — Check the amount and the address
`status` only tells you the transaction is final enough. Before you credit, confirm it paid the right address and amount with [Transaction](https://docs.rarebl.com/api/tx/get).
```bash cURL
curl "https://api.rarebl.com/open/tx/get?chain=btc&id=9dedeb8092d6f026d235e3beb24337ba5657635a38cc949f70c0f28ea15e30db"
```
- **UTXO chains:** look in `data.tx.utxo.outputs[]` for an output whose `address` is yours and whose `value` matches.
- **ETH and TRON:** check `data.tx.account.to` and `data.tx.value`, or for a token payment the matching entry in `data.tx.account.tokenTransfers[]`.
- Compare amounts as decimal strings or with a big-number type, never as floats.
**You should see** your address and the expected amount among the outputs. Only then credit the customer.
## Common errors
| Reply | What it means | What to do |
| --- | --- | --- |
| `API404` | The hash is not found yet: not seen by our node, or wrong. | Treat it as "not seen yet" for a while, then give up after a time you choose. |
| `API400` | The chain or hash is malformed. | Fix the request. |
| `API409` `tx_index_pending` | ETH only: the node is still indexing old transactions. | Retry later: see [Coverage and limits](https://docs.rarebl.com/limits-today). |
| `API429` | Polling too fast. | Wait `Retry-After`; one poll per pending deposit every few seconds is plenty. |
| `API502` | A node is unavailable or syncing. | Back off and retry. |
## Next steps
- Be pushed the events instead: [Webhooks](https://docs.rarebl.com/guides/webhooks) (`tx.confirmations`, `tx.final`).
- Find a transaction from a pasted string: [Look up any address or hash](https://docs.rarebl.com/guides/look-up-anything).
- Move the funds you received: [Watch addresses, get UTXOs and balances](https://docs.rarebl.com/guides/watch-addresses).
- Rate limits and retries: [Errors and rate limits](https://docs.rarebl.com/guides/handle-errors).