API Rate Limits
The TradeZero Trading API enforces per-endpoint request limits on https://webapi.tradezero.com. Limits are applied per API key — your account has one API key pair, and all requests authenticated with it share the same buckets. Exceeding a limit returns 429 Too Many Requests.
At a glance
| Behavior | What integrators see |
|---|---|
| Scope | Per API key (your key pair has its own buckets) |
| Algorithm | Token bucket per route — sustained refill rate plus a burst allowance |
| Throttle signal | HTTP 429 Too Many Requests |
| Response body | Empty |
| Rate-limit headers | No Retry-After or X-RateLimit-* headers on 429 responses |
| Recovery | Pause briefly, then retry — a retry after ~2 seconds succeeds |
| Global cap | No cluster-wide request cap — only the per-key limits apply |
How rate limiting works
Each endpoint has its own token bucket:
- Sustained rate — the number of requests allowed per 1-second window when traffic is spread evenly.
- Burst capacity — how many requests can land instantly before the per-second limit applies. When burst capacity equals the sustained rate, short parallel spikes above the sustained rate trigger
429immediately. When burst capacity is 1, there is effectively no burst buffer — any request above the sustained rate is rejected right away. - Per-endpoint buckets — throttling on
GET /positionsdoes not consume tokens onGET /orders.
Paper and live share the same host and limit model; only credentials differ. Locates endpoints require a live account.
Complete endpoint reference
Limit = requests allowed per second. Burst = how many requests can arrive at once before the per-second limit applies.
Orders
| Method | Path | Limit | Burst |
|---|---|---|---|
POST | /v1/api/accounts/{accountId}/order | 10/s | 10 |
DELETE | /v1/api/accounts/{accountId}/orders/{clientOrderId} | 15/s | 15 |
DELETE | /v1/api/accounts/orders | 3/s | 1 (no burst) |
GET | /v1/api/accounts/{accountId}/is-easy-to-borrow/symbol/{symbol} | 2/s | 2 |
GET | /v1/api/accounts/{accountId}/order/{orderId} | 2/s | 2 |
GET | /v1/api/accounts/{accountId}/orders | 2/s | 2 |
GET | /v1/api/accounts/{accountId}/orders-with-pagination/start-date/{date} | 1/s | 1 |
GET | /v1/api/accounts/{accountId}/orders/start-date/{date} | 1/s | 1 |
GET | /v1/api/accounts/{accountId}/routes | 1/s | 1 |
Positions
| Method | Path | Limit | Burst |
|---|---|---|---|
GET | /v1/api/accounts/{accountId}/positions | 3/s | 3 |
GET | /v1/api/accounts/{accountId}/pnl | 3/s | 3 |
Locates (live account only)
| Method | Path | Limit | Burst |
|---|---|---|---|
POST | /v1/api/accounts/locates/quote | 1/s | 1 |
POST | /v1/api/accounts/locates/accept | 10/s | 10 |
DELETE | /v1/api/accounts/locates/cancel/accounts/{accountId}/quoteReqID/{id} | 2/s | 2 |
POST | /v1/api/accounts/locates/sell | 10/s | 10 |
GET | /v1/api/accounts/{accountId}/locates/history | 2/s | 2 |
GET | /v1/api/accounts/{accountId}/locates/inventory | 2/s | 2 |
Locate quote — 30-second same-symbol rule (separate from 429)
In addition to the 1/s API limit, the locate service enforces a 30-second cooldown per symbol per account: wait at least 30 seconds between POST /locates/quote calls for the same symbol on the same account.
How it behaves:
- Two quotes for the same symbol within the cooldown both return
200 OKsynchronously — the request is accepted and queued. - The cooldown is not expressed as
429at the HTTP layer. Rejection or deduplication surfaces asynchronously inGET /locates/history(for examplelocateStatus: 56with a business reason), not as an immediate throttle response. - Treat 30 seconds per symbol per account as a hard client-side spacing rule regardless of the synchronous status code.
Use distinct symbols when you need to issue multiple quotes in a short window. See Short Locates for the full lifecycle.
Out of scope
| Surface | Notes |
|---|---|
Stock Scanner (api.tradezero.com) | Separate host and limit surface |
| WebSocket streams | Long-lived connections — not REST request buckets. See WebSocket API |
HTTP 429 response
When throttled:
HTTP/1.1 429 Too Many Requests
Content-Length: 0
Every 429 response:
- Status:
429 Too Many Requests - Body: empty (no JSON error envelope)
- Headers: no
Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining, orX-RateLimit-Reset
A 429 is transient — slow down and retry; it is not a permanent ban.
Client integration patterns
After a 429
- Stop the current burst or polling loop for that endpoint.
- Wait at least 1–2 seconds before retrying.
- Retry once with backoff; if
429persists, use exponential backoff with jitter (2 s → 4 s → 8 s, cap at 60 s). - Do not retry in a tight loop on the same endpoint.
Order writes
| Endpoint | Safe pattern |
|---|---|
POST /order | Serial queue with ~100 ms spacing for sustained automation; stay within the 10/s limit |
DELETE /orders/{id} | Space cancels to stay within the 15/s limit |
DELETE /accounts/orders | Max 3/s, no burst — never fire cancel-all in a tight loop |
Portfolio and order reads
| Endpoint | Minimum spacing | Recommended cadence |
|---|---|---|
GET /orders, GET /order/{id}, ETB | ~1 s between calls | Poll until terminal order status, then back off |
GET /orders/start-date/{date}, paginated history, GET /routes | ~1 s | On-demand or low-frequency refresh |
GET /positions | ~2 s sustained; avoid >3 parallel | 5 s background refresh |
GET /pnl | ~2 s sustained | 5 s background refresh |
Prefer WebSocket streams for sub-second order and P&L updates instead of sub-second REST polling.
Locate automation
| Rule | Guidance |
|---|---|
/quote | Max 1 quote/s; no burst |
| Same symbol | Wait ≥ 30 s between quotes for the same symbol on the same account |
| Accept / sell / cancel | Respect 10/s (accept, sell) and 2/s (cancel, history, inventory) |
| Confirmation | POST/DELETE return 200 when queued — confirm state in /locates/history |
Multiple processes or services
Your account has one API key pair. Every REST call authenticated with it — whether from one script, several microservices, or multiple developers — draws from the same per-endpoint buckets. If several processes poll or place orders at once, their combined rate counts against your limits. Coordinate request timing across your integration: use a single polling loop, serialize writes through one queue, and prefer WebSocket streams over parallel REST polling where you need frequent updates.
FAQ
Am I limited per API key or per IP?
Per API key, not per IP. Your account has one API key pair; all requests made with it share that key's buckets regardless of which machine or process sends them.
What should I do after a 429?
Pause, wait 1–2 seconds, retry with backoff. Do not immediately re-fire the same parallel burst.
Do WebSockets count against REST limits?
No. WebSocket connections use a separate model. REST limits apply only to HTTP requests on webapi.tradezero.com.
Does paper differ from live?
Same host and limit model for shared endpoints. Locates are live-only.
Why did my second locate quote return 200 but fail later?
The API acknowledges quotes with 200 before locate business rules are applied. The 30-second same-symbol cooldown and inventory checks surface in /locates/history, not as 429.
Why is cancel-all stricter than cancel-one?
DELETE /accounts/orders has burst capacity 1 — only ~3 requests per second with no parallel buffer. Single-order cancels allow a larger burst (15/s configured).
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
429 on GET /orders or /positions | Polling faster than the limit | Slow to ≥1–2 s between reads; serialize parallel fetches |
429 only in production | Several processes polling or writing in parallel | Coordinate into one polling loop or request queue; slow combined traffic to the limits in this doc |
429 after parallel POST /order | Burst of concurrent order writes | Queue writes; stay within the 10/s limit |
Second locate quote returns 200 but does not appear in inventory | 30 s same-symbol business rule | Wait 30 s; check /locates/history for locateStatus |
Empty 429 body | Expected | Back off; do not parse JSON from the body |
For authentication, see Authentication. For order and locate semantics, see Equity Trading, Positions, and Short Locates.