Skip to content
Last updated

The Fig Markets API implements rate limiting to ensure fair usage and protect our services. Rate limits apply to both the REST API and the WebSocket API.

Rate Limit Basics

Default Limits

All REST endpoints have equal weighting and share the same rate limit, and so do all WebSocket methods.

  • Rate Limit: 1000 requests per minute
  • Time Window: a fixed 1 minute window, which starts with the first request counted in it; the counter resets when the window ends

HTTP API Rate Limiting

REST requests are counted per client IP address, so every API key calling from the same IP address shares one limit.

Rate Limit Headers

Every HTTP response includes rate limit information in the headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1640995200
  • X-RateLimit-Limit: Maximum requests allowed in the time window
  • X-RateLimit-Remaining: Number of requests remaining in the current window
  • X-RateLimit-Reset: Unix timestamp, in seconds, when the current window ends

Rate Limit Exceeded Response

When you exceed the rate limit, you'll receive a 429 Too Many Requests response:

{
  "code": 429,
  "message": "rate limit exceeded",
  "limit": 1000,
  "reset": 1640995200,
  "window": "1m0s"
}

Example: Handling Rate Limits in HTTP Requests

A request refused with 429 can be retried after X-RateLimit-Reset. Sign the retry afresh: a signature older than 60 seconds is refused, and so is one that has already been accepted (see Signing Requests). In the examples below, sendSignedRequest / send_signed_request stands for your own function that signs and sends the request, such as makeRequest in the signing guide.

// JavaScript/Node.js example
async function makeApiRequest(sendSignedRequest) {
  const response = await sendSignedRequest();

  const limit = response.headers.get('X-RateLimit-Limit');
  const remaining = response.headers.get('X-RateLimit-Remaining');
  const reset = Number(response.headers.get('X-RateLimit-Reset'));

  console.log(`Rate limit: ${remaining}/${limit} requests remaining`);

  if (response.status === 429) {
    // Wait until the window ends, then sign and send the request again
    const waitTime = (reset * 1000) - Date.now();
    if (waitTime > 0) {
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }
    return makeApiRequest(sendSignedRequest);
  }

  return response;
}
# Python example
import time

def make_api_request(send_signed_request):
    response = send_signed_request()

    limit = response.headers.get('X-RateLimit-Limit')
    remaining = response.headers.get('X-RateLimit-Remaining')
    reset = int(response.headers.get('X-RateLimit-Reset'))

    print(f"Rate limit: {remaining}/{limit} requests remaining")

    if response.status_code == 429:
        # Wait until the window ends, then sign and send the request again
        wait_time = reset - time.time()
        if wait_time > 0:
            time.sleep(wait_time)
        return make_api_request(send_signed_request)

    return response

WebSocket Rate Limiting

Every WebSocket message counts towards the limit except auth, auth/refresh and heartbeat. Messages are counted per authenticated user once the connection has authenticated, and per client IP address before that.

auth and auth/refresh have their own limit of 120 messages a minute per client IP address (see WebSocket Authentication).

WebSocket Rate Limit Exceeded Response

When you exceed the WebSocket rate limit, you'll receive a JSON-RPC error response:

{
  "jsonrpc": "2.0",
  "id": "your_request_id",
  "error": {
    "code": -32006,
    "message": "Rate limit exceeded",
    "data": {
      "limit": 1000,
      "window": "1m0s",
      "reset": 1640995200
    }
  }
}