Rate Limits
Reya applies limits to account operations, resting orders, WebSocket messages and traffic from each IP address. These limits apply together: staying within an account's allowance does not exempt its requests from connection or IP limits.
Account operation limits
Each accountId has independent allowances for four operation groups.
Standard is the default account tier. Contact the Reya team to arrange Market Maker enrollment and confirm your account's allowances. WebSocket Order Entry access is restricted to approved market-maker source IPs; provide your egress IPs during onboarding. Other clients use REST for order entry.
Create and modify
createOrder, modifyOrder
60 · 5
25,000 · 100
Single cancel
cancelOrder
120 · 10
50,000 · 200
Bulk cancel
cancelAll
10 · 5
100 · 50
Countdown control
cancelAllAfter
100 · 10
100 · 10
The rate is a sustained allowance that replenishes continuously. The burst is the number of operations you can send together when that allowance is fully available. It does not reset at a minute boundary, and unused allowance does not accumulate beyond the burst. For example, Standard create/modify allows five immediate operations after an idle period and replenishes at one operation per second.
Each request uses one operation in its group. cancelAll costs one bulk-cancel operation regardless of the number of orders it targets, including when there are no orders to cancel. A request that later fails validation, risk checks or an open-order cap, or is refused during a matching pause, can still consume an operation; do not count only successful requests.
When an armed countdown expires, its automatic cancellation is not blocked by an exhausted bulk-cancel allowance. It consumes one bulk-cancel operation, which can delay a subsequent explicit cancelAll.
Disarming an active cancelAllAfter countdown consumes an operation but is allowed even when the countdown-control allowance is exhausted. Repeated disarms when no countdown is armed can be rate-limited.
A rate-limited refresh does not extend the countdown: continue tracking the last acknowledged triggerAt. See Cancel-on-Disconnect.
A rate-limit rejection leaves the requested action unapplied. Use the returned retryAfterMs to schedule another attempt.
Resting-order limits
Caps apply per account.
Resting orders across all markets
200
1,500
Resting orders in one market
50
300
Combined resting-order notional
$250,000
$50,000,000
Notional is the sum of remaining quantity × limit price across the account's resting orders, counting bids and asks without netting them.
A new GTC/GTT limit order is checked using its full submitted quantity, even if it could immediately match. An IOC does not occupy resting-order capacity. A modify keeps the same order count but must fit the notional cap using its proposed quantity and price.
Armed SL/TP orders do not occupy these caps. Each account can have one stop-loss and one take-profit per market. A fired GTC/GTT child that rests contributes to the account's resting-order totals. Trigger creation and modification consume the create/modify allowance, but automatic firing does not require a new client request or consume that allowance.
WebSocket message limits
Each connection has an inbound message allowance, independent of account-operation limits. It counts client application messages, including JSON pings, subscriptions and order requests, even if a message is invalid. Server-to-client market-data updates do not consume this allowance.
WebSocket Order Entry
2,000
4,000
WebSocket Info
20
1,200
If a connection exceeds its message allowance, it closes with code 4029 and a reason of the form MSG_RATE_EXCEEDED retry_after_ms=<n>. Wait at least the indicated milliseconds, reconnect with backoff and resume at a lower message rate. Pace subscription replay as well as order traffic. Protocol-level ping/pong control frames are separate from these application messages; see Heartbeats.
Info subscription limits
These apply alongside the message limits above.
Subscription requests
10/second · burst 40
Per connection
Subscription requests
40/second · burst 160
Per IP, shared across connections
Active subscriptions
500
Per connection
Distinct wallet subjects
10
Per IP, shared across connections
A wallet counts once toward the distinct-wallet cap, even when subscribed to through multiple channels or connections. A subscription-rate rejection returns an error without closing the socket or sending the subscription's snapshot; retry with backoff.
IP request and connection limits
The limits below are total allowances per public IP, shared across all of your clients and accounts using that IP. Account tiers do not increase these allowances. Order Entry and Info have separate simultaneous-connection caps but share one new-connection allowance across all three WebSocket hostnames.
REST order management
2,000 requests/minute
One shared bucket on api.reya.xyz for createOrder, modifyOrder, cancelOrder, cancelAll and cancelAllAfter
Other REST requests
1,500 requests/minute
All other routes on api.reya.xyz, in a separate bucket
New WebSocket connections
300 attempts/minute
One shared bucket across ws-exec.reya.xyz, ws.reya.xyz and ws-gke.reya.xyz
Simultaneous Order Entry connections
20 total
Per IP
Simultaneous Info connections
100 total
Per IP
The REST and WebSocket-upgrade limits use 60-second counting windows. New-connection limits count HTTP upgrade attempts, including rejected handshakes, but do not count messages on an established socket.
Clients behind the same public IP share its limits, even when they trade different accounts. Reuse established connections, avoid unnecessary polling, and stagger reconnections across your clients. Closing an unused connection can free connection capacity; repeatedly attempting to reconnect does not.
For IPv6, Info shares its application IP allowances across addresses in the same /64. Order Entry and edge counters use the full source IP address.
Error responses and recovery
Order-management rejections use HTTP 400 on REST. The body's error field identifies the outcome; a retryable rejection is not necessarily HTTP 429. WebSocket Order Entry returns the same error object inside its normal { "ok": false, "error": ... } response.
For example, an account-operation rate rejection can carry:
retryAfterMs is a positive duration in milliseconds when provided. Wait at least that long and coordinate retries across clients sharing the account. Other traffic can consume the replenished allowance, so the hint does not reserve the next operation. Order-management retry hints are carried in the body, not a Retry-After header.
RATE_LIMITED_ERROR
The account exhausted the allowance for this operation group
Respect retryAfterMs when present and reduce the sending rate; use backoff if no hint is present
OPEN_ORDER_COUNT_EXCEEDED_ERROR
A new order would exceed the account-wide or per-market resting-order count
Cancel orders or wait for them to fill; elapsed time alone does not release a slot
OPEN_ORDER_NOTIONAL_EXCEEDED_ERROR
A create or modify would exceed combined resting-order notional
Reduce the proposed notional or release capacity through cancellations or fills
CAPACITY_LIMITED_ERROR
New orders and modifications are temporarily restricted because of venue load
Back off with jitter; cancellation and countdown requests remain available under their own limits
The count, notional and capacity errors carry no retryAfterMs. Staying within your account limits does not guarantee acceptance during a capacity restriction, and a capacity rejection does not consume the create/modify allowance.
Retry only while the intended action is still appropriate. Sign a new request with a fresh nonce and a valid signature deadline; ensure any order expiry is still valid. Follow the nonce rules. A transport timeout or disconnect is different from an explicit rejection: follow Handling ambiguous outcomes and reconcile the original request before sending another one.
IP-limit rejection and recovery
Exceeding an edge limit blocks all requests in that rule's scope from the IP for 60 seconds, returning HTTP 429, including during a WebSocket upgrade. In particular, exhausting the REST trading bucket also blocks REST cancellations and countdown refreshes. Separate account-level cancellation allowances do not bypass this block. Exhausting the shared WebSocket-upgrade allowance blocks new connections to all three WebSocket hostnames. These edge blocks do not close established sockets; their account and connection limits still apply.
The edge response has error: "rate_limited", scope: "ip" and retryAfterSeconds: 60. It is separate from the order-management error contract and supplies no Retry-After header. Wait at least 60 seconds after an edge rejection, then retry with jitter and a lower request rate. The one-minute allowance can still be exhausted after the block expires, so increase backoff if rejected again. Browser clients can see a network error instead of a readable 429 because the block response has no CORS headers; if the outcome of an order request is unclear, reconcile before retrying.
For a simultaneous-connection refusal, reduce open connections from that IP and back off. A refusal can arrive as HTTP 429 during upgrade or as close code 4029 with IP_CONN_LIMIT_EXCEEDED max_conns=<n>. Unlike the timed edge block, this cap does not provide a time at which capacity is guaranteed to become free.
Last updated