Reference
Rate limits
Limits are generous for real integrations and strict for runaway loops. Every limited answer tells you how long to wait.
#Partner API
| Limit | Default | When exceeded |
|---|---|---|
| Requests per minute, per company (all keys together) | 120 (set by the platform owner per company) | 429 rate_limited + Retry-After |
Clients per page (GET /clients) | limit up to 500 | Paging via updated_since / cursor |
| Wrong keys per minute, per address | 60 | 429, wait one minute |
| Webhook deliveries | unlimited; one HTTP call per event per endpoint, 10 s timeout | Retries, then paused endpoint |
GET /me returns the company's current limit. Poll with updated_since instead of re-reading everything, and prefer webhooks to polling.
#Trading API
| Limit | Default |
|---|---|
| Requests per minute, per key | 1 200 (broker-set, 10 - 12 000) |
| Requests per minute, per client | 2 x the key limit, across all keys |
| Order actions per second, per key | 10 (broker-set, 1 - 50) |
| Order actions per second, per trading account | 10 (broker-set, 1 - 50) |
| Keys per client | 5 (broker-set, 1 - 20) |
| Wrong keys per minute, per address | 60, then 429 too_many_invalid_keys |
| Symbols per GET /quotes | 100 |
| Bars per GET /bars | 5 000 |
| Stream ticket | single use, 60 s |
Every Trading API answer carries the per-key window:
Response headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 1200
X-RateLimit-Remaining: 1187
X-RateLimit-Reset: 1762862460429 rate_limitedwithdetails.scope = "key"or"client"andRetry-After.429 order_rate_limitedwhen more than 10 order actions a second hit one key or one trading account.503 rate_limit_unavailable: the limit store is down; order actions are refused and nothing was placed. Reads continue.
#WebSocket
| Connections per client | 5 |
| Connections per key | 3 |
| Connections per address | 50 |
| Symbols per connection | 100 |
| Client messages per second | 10 (burst 20) |
| Connection lifetime | 15 min, then close 1000 lifetime - reconnect with a new ticket |
| Heartbeat | every 15 s (server -> client) |
| Client message size | 4 096 bytes |
Over the message rate the server answers { "type": "error", "code": "rate_limited" }; more than 20 errors close the socket with too_many_errors.
#FIX
| Transport | TCP + TLS 1.2 or newer |
| Version | FIX 4.4 |
| HeartBtInt (108) | 5 - 120 s |
| Messages per second per session | 50 (burst 100) |
| Logons per minute per address | 30 |
| Connections per address | 20 |
| Symbols per QUOTE session | 100 |
| Quote updates | at most one X per symbol every 250 ms |
#Backing off
Retry 429 and 503 after Retry-After seconds (fall back to exponential backoff with jitter). Never retry 4xx other than 429. For order actions, look the order up before a retry.
Retry helper
async function call(url, init, tries = 5) {
for (let i = 0; i < tries; i++) {
const res = await fetch(url, init);
if (res.status !== 429 && res.status !== 503) return res;
const wait = Number(res.headers.get('retry-after') ?? 2 ** i) * 1000;
await new Promise((r) => setTimeout(r, wait + Math.random() * 250));
}
throw new Error('gave up after ' + tries + ' tries');
}import time, random, requests
def call(method, url, tries=5, **kw):
for i in range(tries):
res = requests.request(method, url, **kw)
if res.status_code not in (429, 503):
return res
wait = float(res.headers.get("Retry-After", 2 ** i))
time.sleep(wait + random.random() * 0.25)
raise RuntimeError(f"gave up after {tries} tries")func call(c *http.Client, req *http.Request) (*http.Response, error) {
for i := 0; i < 5; i++ {
res, err := c.Do(req)
if err != nil { return nil, err }
if res.StatusCode != 429 && res.StatusCode != 503 { return res, nil }
wait, _ := strconv.Atoi(res.Header.Get("Retry-After"))
if wait == 0 { wait = 1 << i }
res.Body.Close()
time.Sleep(time.Duration(wait)*time.Second + time.Duration(rand.Intn(250))*time.Millisecond)
}
return nil, errors.New("gave up")
} Need more?
Trading API limits are set per brand by the broker (requests per minute 10 - 12 000, orders per second 1 - 50, keys 1 - 20). Partner API limits are set per company by the platform owner. Ask your account manager.