For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

  1. Call GET /v1/health without auth. This only proves the Trading API is reachable.

  2. Call signed GET /v1/me. Continue only when account_mode is advanced and the account has the capability you need.

  3. Call signed GET /v1/markets. Select a market by returned market_id, not by transforming a symbol. Use the market's top-level instrument_id when you need to join to balances.

  4. Call signed GET /v1/account/limits?market_id=.... Pace create-order submissions from order_rate_limits.max_orders_per_second and the Retry-After header from 429 responses. The limit counts submissions, not fills, and unused capacity does not accumulate into a larger burst.

  5. Call signed GET /v1/trading-accounts and GET /v1/currency-trading-accounts. Confirm you have inventory for sells and USD for buys.

  6. Build the order body. For limit orders, price must be a decimal string such as "0.68", and quantity must be a whole integer lot count.

  7. Submit one order with a unique client_order_id.

  8. Confirm the result with GET /v1/orders?status=open and, 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?