Skip to main content

Overview

Rate limits protect the API from abuse and ensure fair usage for all users. When you exceed a rate limit, the API returns a 429 Too Many Requests response with a Retry-After header and a retryAfter field indicating how many seconds to wait before retrying.

API key rate limits

Authenticated endpoints are rate-limited per API key based on whether the endpoint is a read or write operation.
TypeLimitScope
Read endpoints30 requests/secondPer API key
Write endpoints20 requests/secondPer API key
Read endpoints are those that require X-Public-Key only. Write endpoints are those that require X-Public-Key, X-Timestamp, and X-Signature. See the Authentication guide for details. When the limit is exceeded:
{
  "message": "Rate limit exceeded. Please try again later.",
  "retryAfter": 1
}
The response also includes a Retry-After header with the number of seconds to wait.

API key management

API key management endpoints are rate-limited per session token to prevent abuse. Each user can have a maximum of 2 active API keys at any time.
OperationLimitWindowScope
Create API key2 requests30 minutesPer session
Revoke API key2 requests30 minutesPer session
Rotate API key2 requests30 minutesPer session
Rotation shares the revoke limit since it revokes the existing key and creates a new one. When the limit is exceeded:
{
  "message": "Rate limit exceeded. Please try again later.",
  "retryAfter": 900
}
The retryAfter value reflects the actual time remaining until the next request is allowed.

Login endpoint

The login endpoint (POST /v1/user/login) is rate-limited to 1 request per 2 minutes per email address.
EndpointLimitWindowScope
POST /v1/user/login1 request2 minutesPer email address
When the limit is exceeded:
{
  "message": "Too many login attempts. Please try again later.",
  "retryAfter": 120
}

Handling rate limit errors

Node.js
async function fetchWithRetry(url, options) {
  const response = await fetch(url, options);

  if (response.status === 429) {
    const { retryAfter } = await response.json();
    console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);
    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
    return fetchWithRetry(url, options);
  }

  return response.json();
}

Best practices

  • Handle 429 gracefully — if you receive a rate limit response, wait for the retryAfter duration before retrying.
  • Cache your session token — after a successful login, store the returned token and deviceId and reuse them for subsequent API key operations. There’s no need to log in again for each request.
  • Don’t poll the login endpoint — the login endpoint is intended for one-time session creation, not repeated calls.
  • Batch where possible — if you need data for multiple markets, use list endpoints instead of making individual requests.