Trading bot safety patterns
Guardrails for scripts that place real Trading API orders.
Use these patterns when you automate Advanced Mode trading. The goal is simple: check account mode, balances, market controls, and rate limits before placing an order; make retries explicit; and fail closed when the API says the request is invalid.
This applies equally to bots that resell unused inventory. A sell against your Trading account balance is the same order flow as a buy, so the same checks and the same stop signals below apply.
Minimum viable safe bot loop
Call
GET /v1/healthwithout auth. This only proves the Trading API is reachable.Call signed
GET /v1/me. Continue only whenaccount_modeisadvancedand the account has the capability you need.Call signed
GET /v1/markets. Select a market by returnedmarket_id, not by transforming a symbol. Use the market's top-levelinstrument_idwhen you need to join to balances.Call signed
GET /v1/account/limits?market_id=.... Pace create-order submissions fromorder_rate_limits.max_orders_per_secondand theRetry-Afterheader from 429 responses. The limit counts submissions, not fills, and unused capacity does not accumulate into a larger burst.Call signed
GET /v1/trading-accountsandGET /v1/currency-trading-accounts. Confirm you have inventory for sells and USD for buys.Build the order body. For limit orders,
pricemust be a decimal string such as"0.68", andquantitymust be a whole integer lot count.Submit one order with a unique
client_order_id.Confirm the result with
GET /v1/orders?status=openand, after fills,GET /v1/trades?order_id=....
Treat these responses as stop signals
403 auto_mode_trading_restricted means the account is still in Auto Mode. Do not retry order mutations until the account is switched to Advanced Mode.
422 validation_error means the request shape is wrong. Fix the request before retrying. Common causes are numeric JSON prices, unsupported time_in_force, invalid status filters, or fractional quantities.
422 quantity_below_min_order_size, lot_size_violation, or tick_size_violation means the order does not match market controls. Read errors.context.limits, round the order, and submit a new client_order_id.
429 means you hit an order submission limit. Sleep for the retry-after header when present; otherwise use exponential backoff with jitter.
Small Python skeleton
Run real-order scripts with unbuffered logging, for example python3 -u bot.py, so fills, retries, and stop signals are visible immediately.
Last updated
Was this helpful?