Skip to main content
The CSBoard API enforces per-key rate limits to keep the service stable for all users. If you exceed a limit you receive a 429 response immediately — no request is partially processed. Build your client to inspect the Retry-After header and pause before retrying, rather than hammering the endpoint in a tight loop.

Limits by endpoint

All limits are per API key and reset on a rolling 60-second window.
LimitEndpoint(s)
30 / minListings, prices, currency, balance, and order status — all standard GET endpoints
30 / minPOST /v1/orders (places a buy order and spends real money)
1 / minGET /v1/prices/snapshot.ndjson.gz (bulk compressed snapshot)
Sending more than 30 requests with invalid or missing API keys from the same IP address within one minute triggers an automatic 5-minute IP-level ban. During the ban every request from that IP returns 401 too_many_failed_auth regardless of which key is used. Rotate to a valid key and wait out the cooldown before retrying.

429 response format

When you exceed a standard endpoint limit the API returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 14
Content-Type: application/json

{ "code": "rate_limit_exceeded", "detail": "Rate limit exceeded. Retry after 14 seconds." }
The Retry-After header value is an integer number of seconds you must wait before the next request will succeed. The bulk snapshot endpoint uses a distinct error code when rate-limited:
{ "code": "snapshot_rate_limited", "detail": "Snapshot rate limit exceeded. Retry after 60 seconds." }

Handling 429s in your client

Read Retry-After and sleep for at least that many seconds before retrying. The example below shows a simple retry loop in bash:
while true; do
  RESPONSE=$(curl -si https://csboard.com/v1/listings \
    -H "Authorization: Bearer csb_pub_...")

  STATUS=$(echo "$RESPONSE" | head -1 | awk '{print $2}')

  if [ "$STATUS" = "429" ]; then
    RETRY_AFTER=$(echo "$RESPONSE" | grep -i "retry-after" | awk '{print $2}' | tr -d '\r')
    echo "Rate limited. Waiting ${RETRY_AFTER}s..."
    sleep "$RETRY_AFTER"
  else
    echo "$RESPONSE" | tail -1  # print body
    break
  fi
done
Add a small jitter (e.g. sleep $((RETRY_AFTER + RANDOM % 5))) when running multiple workers in parallel so they don’t all resume at the same instant and immediately re-trigger the limit.

Raising your limits

The default limits suit most integrations, but if you have a high-throughput use case — such as a data pipeline or a high-frequency trading bot — contact us to discuss a higher per-key limit for your account.