Rate Limiting & Quotas
Per-Minute Rate Limiting
Each plan has a per-minute request limit. Exceeding this limit returns HTTP 429.
Quota System
API usage is measured in blocks. Each request deducts blocks from your monthly block budget based on the block range requested.
Cost formula: max(100, round(block_range × network_discount × aggregate_discount))
- block_range:
block_end - block_start, or estimated from time range using blocks-per-day - network_discount: 1.0 (default), 0.2 (ARB)
- aggregate_discount: 0.5 for
/aggregateendpoints, 1.0 otherwise - Minimum cost: 100 blocks per request
Calculate Cost Before Querying
Use the POST /v1/calculate-cost endpoint to preview how many blocks a query will cost without deducting from your quota. This lets you validate block ranges and plan usage before committing.
curl -X POST -H "X-API-Key: $API_KEY" -H "Content-Type: application/json"
-d '{"query": "/v1/erc20/events/transfer?network=ETH&block_start=24000000&block_end=24010000&token=USDT"}'
"https://api.defistream.dev/v1/calculate-cost" Response:
{
"query": "/v1/erc20/events/transfer?network=ETH&block_start=24000000&block_end=24010000&token=USDT",
"cost": 10000,
"quota_remaining": 500000,
"quota_remaining_after": 490000
} Response Headers
Every response includes these headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Remaining monthly block budget |
X-Request-Cost | Blocks deducted for this request |
X-RateLimit-Reset | Seconds until rate limit window resets |
Retry-After | Seconds to wait (only on 429 responses) |
Handling Rate Limits
When you receive a 429 response:
- Read the
Retry-Afterheader - Wait that many seconds before retrying
- Implement exponential backoff for repeated failures
import time
import requests
def fetch_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
return response
raise Exception("Max retries exceeded")