Monitor balances, deposits, withdrawals, and order activity across Main, Trade, and Collateral accounts using REST polling and WebSocket streams.
Monitor account state across Main, Trade, and Collateral balances using REST endpoints and WebSocket streams. Payment processing backends and trading systems consume the same account state through different mechanisms.
Payment processing integrations (deposit/withdrawal monitoring) — focus on balance monitoring and deposit/withdrawal tracking; Main balance does not support WebSocket streaming, so webhooks and REST polling are the primary mechanisms.
Trading integrations (bots, dashboards) — focus on balance monitoring and order activity monitoring via WebSocket for real-time state.
For an explanation of account types and how funds move between accounts, see Balances & Transfers.Every endpoint and stream in this guide operates on the account that owns the API key — to monitor a sub-account, use the sub-account’s dedicated key. A master-account key can also query a sub-account’s Main, Spot, and Collateral balances via POST /api/v4/sub-account/balances. See Sub-Accounts for key management.
Main balance does not have a WebSocket subscription channel. Use webhooks for real-time notification of the transaction types in the webhook event catalog, with POST /api/v4/main-account/history polling as a fallback. For a complete view of Main balance state, poll POST /api/v4/main-account/balance.
The following example assumes an authenticated WebSocket session. Private channels require authorization before subscribing — see WebSocket Quickstart — Authenticate for private channels for the full authentication flow. Subscribing to a private channel without authorization fails with an authorization error — check the error field on the subscription response.
Python
wscat
import json, websockets, asyncioasync def monitor_balance(): async with websockets.connect("wss://api.whitebit.com/ws") as ws: # Authenticate first — see "Authenticate for private channels" # in the WebSocket Quickstart. Private channels require # authorization before subscribing. # Subscribe to spot balance changes. # params: [] subscribes to all assets. # Pass specific tickers (e.g., ["USDT", "BTC"]) to filter updates. await ws.send(json.dumps({ "id": 1, "method": "balanceSpot_subscribe", "params": [] })) async for message in ws: data = json.loads(message) # Subscription confirmation has a "result" key. # Balance updates have a "method" key set to "balanceSpot_update", # with "params" as an array of asset-keyed update objects. if data.get("method") == "balanceSpot_update": for update in data["params"]: for asset, info in update.items(): print(f"Balance change: {asset} available={info['available']} freeze={info['freeze']}")asyncio.run(monitor_balance())
# Uses the send_request helper from the "Fetch Trade balance" example.# Fetch recent deposits (transactionMethod: 1 = deposits, 2 = withdrawals)deposits = send_request("/api/v4/main-account/history", { "transactionMethod": 1, "limit": 50})for record in deposits.get("records", []): print(f"{record['ticker']}: {record['amount']} — status {record['status']}")
The status field is a numeric code — for example 3 and 7 mean credited, and deposits can sit frozen under Travel Rule statuses 27/28. See the status state machines in Payment Integration.The endpoint paginates with limit (default 50, max 500) and offset — page until fewer than limit records return. It accepts no date filters, and pagination is capped at offset + limit ≤ 10000. For reconciliation, page from offset 0 until reaching the last processed transaction.
For real-time deposit and withdrawal notifications, configure webhooks. Webhook delivery is best-effort — a small number of retries spaced roughly an hour apart over a window of about one day. Treat the exact cadence as not contractually guaranteed.Recommended reconciliation approach:
Primary: Webhooks — process events on arrival
Fallback: REST polling — periodically query the history endpoint to catch any events missed during webhook downtime or after the retry window expires
See Webhooks for setup, signature verification, and event types. For the full deposit/withdrawal lifecycle including status state machines and fee calculation, see Payment Integration.
Query order history for filled and canceled orders:Endpoint:POST /api/v4/trade-account/order/historyFor B2B accounts, canceled orders are not recorded in order history — to obtain canceled-order data, contact support or the assigned account manager.
# Uses the send_request helper from the "Fetch Trade balance" example.history = send_request("/api/v4/trade-account/order/history", {"market": "BTC_USDT"})for market, orders in history.items(): for order in orders[:5]: print(f" {order['side']} {order['amount']} @ {order['price']} — {order.get('type', 'unknown')}")
Order history paginates with the same limit (default 50, max 500) and offset parameters. Date filtering is limited to a 31-day window between startDate and endDate, with the earliest reachable date 6 months back — see Query Executed Orders.
For final order state with aggregate data (fully filled or canceled), see also Orders Executed.The two channels use different params shapes: ordersPending_subscribe accepts a flat list of markets (["BTC_USDT"]), while deals_subscribe accepts a list of market lists ([["BTC_USDT"]]).
Python
wscat
# Add these calls inside monitor_balance() after the# balanceSpot_subscribe message. Subscribe to order updates and trade fills.await ws.send(json.dumps({ "id": 2, "method": "ordersPending_subscribe", "params": ["BTC_USDT"]}))await ws.send(json.dumps({ "id": 3, "method": "deals_subscribe", "params": [["BTC_USDT"]]}))
When using REST polling, align the interval with the use case and the endpoint rate budget. See Rate Limits & Error Codes for per-scope request limits.
Use case
Endpoint
Suggested interval
Balance dashboard
POST /api/v4/trade-account/balance
5–30 seconds
Deposit detection (fallback)
POST /api/v4/main-account/history
5 minutes
Order history reconciliation
POST /api/v4/trade-account/order/history
30–60 seconds
POST /api/v4/main-account/history has a much smaller rate budget (200 requests/10 s) than the trade endpoints (12,000 requests/10 s) — keep its polling interval in minutes, not seconds.Polling loops need failure handling. On HTTP 429, back off and resume — see Building a Trading Bot — Rate limit backoff; retried requests need a new, larger nonce (see Authentication). On WebSocket, check the error field on every response before treating a subscription as active.