Rate Limits
Sequence enforces per-client API rate limiting with a token-bucket model.
REST API Limit Model
-
Limits are applied per authenticated client (
client_id), not per source IP. Two API keys for the same account share that account's profile-level limit; two keys for different accounts have fully isolated buckets. -
The configured limit comes from your account profile (
rate_limit_qps). -
The implementation is a token bucket: bucket capacity =
2 × qps(lets you absorb a brief burst after idle), refill =qpstokens/second. -
If no profile-specific value is set, default behavior is low-QPS safe mode.
-
Default per-tier values:
Tier Sustained QPS Burst capacity free5 10 paid/pro/enterprisevaries — set on profile 2 × qps -
Exceeding limit returns
429 Too Many Requestswith:
{
"error": "Rate limit exceeded"
}Docs examples should not hardcode one global QPS number. Your effective limit depends on your account profile and environment configuration.
SSE Streams
SSE endpoints are long-lived authenticated HTTP connections:
GET /v1/tca/stream— post-completion TCA reportsGET /v1/risk/stream— risk-state changesGET /v1/alerts/stream— user-defined alert triggers
For order and fill streams, use the unified WebSocket /v1/stream (subscribe to the orders and fills channels).
Practical guidance:
- Run one consumer per stream type per application instance.
- Reconnect with backoff on disconnect.
- Filter server-side where supported (
node_order_id,edge_id) to reduce client load.
WebSocket Market Data
GET /v1/stream is the unified WebSocket — subscribe to prices:<symbol>, book:<symbol>, orders, fills, routing, tca, funding, and more on a single connection.
Recommended auth flow:
GET /v1/ws/ticketwith bearer auth- Connect with
?ticket=<short-lived-ticket>
This avoids putting long-lived API keys in URLs.
Headers and Retry Behavior
Current API behavior to rely on:
429indicates throttling.- Error body includes a structured envelope with
error.code="RATE_LIMITED"and arequest_idfor correlation.
{
"error": {
"code": "RATE_LIMITED",
"message": "rate limit exceeded",
"request_id": "550e8400-..."
}
}Do not assume standardized rate-limit headers (such as X-RateLimit-*) are always present.
Client Best Practices
- Prefer streaming (
SSE/WebSocket) over polling hot endpoints. - Use exponential backoff on
429,503, and disconnects. - Batch reads where possible (
/v1/nbbo, paginated/v1/orders). - Use separate API keys per service to isolate load.
Minimal retry template:
async function withBackoff(requestFn, retries = 4) {
for (let i = 0; i <= retries; i++) {
const res = await requestFn();
if (![429, 503].includes(res.status)) return res;
const delayMs = Math.min(1000 * 2 ** i, 8000);
await new Promise((r) => setTimeout(r, delayMs));
}
throw new Error('request failed after retries');
}