requests and websockets libraries.
Prerequisites
- A WhiteBIT account (register)
- An API key with Trading permission (create one)
- Funds in the Trade balance — transfer from Main balance if needed (see Balances & Transfers)
- Familiarity with HMAC-SHA512 signing — see Authentication
- Python 3.7+ with
requestsandwebsocketspackages installed
Architecture overview
A trading bot operates as a continuous loop:- Market data — receive prices and orderbook updates via WebSocket (or REST polling for lower-frequency strategies)
- Signal generation — apply strategy logic to determine when and what to trade
- Order execution — place orders via REST API (single or bulk)
- Fill monitoring — track order fills and state changes via WebSocket
- Position management — update internal state, replace filled orders, manage risk
Market data ingestion
REST polling
For strategies that do not require sub-second data, poll market data via REST:- cURL
- Python
GET /api/v4/public/ticker— 24h ticker statistics for all marketsGET /api/v4/public/orderbook/{market}— orderbook snapshot with configurable depth
WebSocket streaming
For real-time data, subscribe to WebSocket market streams:| Channel | Subscribe method | Data |
|---|---|---|
| Last Price | lastprice_subscribe | Price updates on every trade |
| Depth | depth_subscribe | Orderbook depth updates |
depth_update messages carry an update_id. Non-contiguous IDs indicate
a missed message — resnapshot by unsubscribing and re-subscribing. See
WS Quickstart — State recovery after reconnect
for the full pattern.Order placement
All private endpoint examples in the guide use the followingsend_request helper for HMAC-SHA512 signing:
send_request uses a millisecond nonce. If multiple threads call the helper
in the same millisecond, the server rejects the duplicate via its nonceWindow
(±5 seconds). The helper below uses a monotonic counter protected by a lock
— safe under concurrent callers (for example, the kill-switch heartbeat
thread and the strategy thread placing orders simultaneously).authorize handshake. The helper below fetches a token via REST (rate limit: 10 requests / 60 s) and sends the authorize message. Call it once per WebSocket connection, before any private subscribe:
Single order
Place a limit order using the order creation endpoint: Endpoint:POST /api/v4/order/new
- cURL
- Python
For bot integrations, include
clientOrderId in the request to map fills
back to internal strategy state without depending on the server-assigned
orderId. The identifier is preserved across order/modify calls (modify
issues a new orderId but retains the caller-supplied clientOrderId),
which makes it the right key for order reconciliation. See
Client Order ID for usage patterns.Bulk orders
Place up to 20 limit orders in a single request — significantly reducing round trips for multi-order strategies. Endpoint:POST /api/v4/order/bulk
The bulk endpoint accepts up to 20 limit orders per request. All orders in a batch must target the same market pair. Partial failures are possible — always check each order result individually.
Kill-switch setup
The kill-switch automatically cancels all active orders after a configurable timeout. The kill-switch is a critical safety mechanism for unattended bots — if the bot process crashes or loses connectivity, the kill-switch prevents stale orders from executing. Endpoints:POST /api/v4/order/kill-switch— activate or refresh the timerPOST /api/v4/order/kill-switch/status— check current timer state
Activate kill-switch
The kill-switch scope defaults to all order types (spot, margin, futures).
To scope it to just spot orders — for example, when the same account runs
futures positions that must not be canceled by a spot kill-switch — pass
"types": ["spot"] in the request.Heartbeat refresh loop
The bot must refresh the kill-switch before the timer expires. If the bot fails to refresh, all orders cancel automatically.Deactivate kill-switch
WebSocket fill monitoring
Subscribe to account streams to receive real-time notifications for order state changes and trade executions:| Channel | Subscribe method | Events |
|---|---|---|
| Deals | deals_subscribe | Trade executions (fills) |
| Orders Pending | ordersPending_subscribe | Order placed, partially filled, canceled |
Error handling
Robust error handling is critical for unattended bots. Handle the following scenarios:Rate limit backoff
Error classification
| Signal | Example | Action | Auto-retry? |
|---|---|---|---|
HTTP 429 | — | Exponential backoff (1s → 2s → 4s → max 30s, with jitter) | Yes |
HTTP 401 | — | Stop trading, investigate — never auto-retry auth failures | No |
HTTP 422 + body code: 5 | Not enough balance | Log, skip order, re-check balance | No |
HTTP 422 + body code: 30/31/32/33 | Validation failed (field-specific) | Fix the request — inspect the errors map | No |
HTTP 422 + body code: 10 | Market not found or disabled | Skip market, check status via REST | No |
HTTP 5xx | — | Backoff and retry | Yes |
Reconnection and recovery
WebSocket connections drop due to network issues, server maintenance, or idle timeouts. A production bot must handle disconnections without losing state.Ping/pong keepalive
Send periodic ping messages to detect stale connections before a timeout occurs:The keepalive function above is shown in isolation. In production, integrate
ping/pong handling into the main message loop — running a separate
recv()
consumer conflicts with the primary message loop and causes missed messages.Reconnection with exponential backoff
Auto-resubscription after reconnect
After reconnecting, the bot must re-authenticate (for private channels) and re-subscribe to all channels. Resubscription ensures fresh data snapshots replace any state that went stale during the disconnection.State reconciliation
WebSocket streams do not replay messages that arrived during a disconnection. After reconnecting and re-authenticating, reconcile local state against the authoritative server state:reconcile_state(MARKET, grid_orders) after authenticate_ws(ws) and before re-subscribing. For a per-fill audit trail, also query POST /api/v4/trade-account/executed-history to see fills that happened during the disconnect.
Worked example: Grid bot
A grid bot places buy and sell orders at fixed price intervals around a center price. When a buy fills, a sell is placed one grid level above. When a sell fills, a buy is placed one grid level below. The strategy profits from price oscillation within the grid range.The grid bot uses synchronous
requests.post() calls inside an async context
for simplicity. In production, synchronous HTTP calls block the event loop and
delay WebSocket message processing. Wrap REST calls in asyncio.to_thread()
for concurrent execution.- Initialization — fetches the current market price, snaps to the nearest grid level, and places buy orders below and sell orders above using the bulk endpoint
- Kill-switch — a background thread refreshes the kill-switch every 90 seconds with a 120-second timeout, ensuring all orders cancel if the bot stops
- Fill monitoring — WebSocket
deals_subscribeandordersPending_subscribechannels detect when a grid order fills - Order replacement — each filled buy triggers a sell one grid level above; each filled sell triggers a buy one grid level below
- Reconnection — the outer loop reconnects automatically if the WebSocket connection drops
What’s Next
Account Monitoring
Monitor balances, deposits, and order activity across all account types.
Client Order ID
Attach custom identifiers to orders for tracking across systems.
Rate Limits & Errors
Per-endpoint rate limits, error codes, and retry strategies.