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.