Rate Limits

Rate limits protect platform stability and ensure fair usage across all organisations. Limits are applied per API key and reset on a rolling window.

Response Headers

Every API response includes rate limit headers so you can track your usage:

X-RateLimit-Limit: 300        # Maximum requests in the window
X-RateLimit-Remaining: 287    # Requests remaining
X-RateLimit-Reset: 1711036800 # Unix timestamp when the window resets
Retry-After: 12               # Seconds until next request (only on 429)
Read operations
300 req/minburst: 50 req/s

GET /objects, GET /templates, GET /wallets, GET /indexer/*

Write operations
60 req/minburst: 10 req/s

POST /objects, PUT /objects/*, POST /templates

Event Bus
2,000 actions/sec per org

POST /ebus/execute, POST /ebus/actions/batch

Search / Indexer
120 req/minburst: 20 req/s

GET /indexer/search, GET /indexer/query

Storage uploads
30 req/minburst: 5 req/s

POST /storage/upload

Webhooks management
30 req/minburst: 5 req/s

POST /webhooks, PUT /webhooks/*

Handling Rate Limits in the SDK

The TypeScript SDK automatically retries on 429 responses with exponential backoff when you configure the retry option:

import { DualClient, DualRateLimitError } from "dual-sdk";

const client = new DualClient({
  token: process.env.DUAL_API_KEY,
  authMode: "api_key",
  retry: { maxAttempts: 3 },  // auto-retries on 429 with backoff
});

try {
  const objects = await client.objects.list({ limit: 50 });
} catch (err) {
  if (err instanceof DualRateLimitError) {
    console.log(`Rate limited. Retry after ${err.retryAfter}s`);
  }
}

Need higher limits? Contact support to discuss enterprise rate limit tiers. See also the Error Reference for handling all error types.