- Docs
- Developer Kit
- Rate Limits
Rate Limits
Rate limit tiers for all Dual API endpoint groups, with response headers and SDK handling guidance.
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 windowX-RateLimit-Remaining: 287 # Requests remainingX-RateLimit-Reset: 1711036800 # Unix timestamp when the window resetsRetry-After: 12 # Seconds until next request (only on 429)
Limits by Endpoint Group
Read operations, 300 req/min · burst: 50 req/s
Applies to: GET /objects, GET /templates, GET /wallets, GET /indexer/*
Write operations, 60 req/min · burst: 10 req/s
Applies to: POST /objects, PUT /objects/*, POST /templates
Event Bus, 2,000 actions/sec per org
Applies to: POST /ebus/actions, POST /ebus/actions/batch
Search / Indexer, 120 req/min · burst: 20 req/s
Applies to: GET /indexer/search, GET /indexer/query
Storage uploads, 30 req/min · burst: 5 req/s
Applies to: POST /storage/upload
Webhooks management, 30 req/min · burst: 5 req/s
Applies to: 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.