Delta Exchange API Rate Limit: What Every Trader Must Know
Master Delta Exchange API rate limits to build reliable trading bots. Learn practical strategies, code examples, and error handling to avoid getting throttled.
Master Delta Exchange API rate limits to build reliable trading bots. Learn practical strategies, code examples, and error handling to avoid getting throttled.
Every crypto exchange enforces API rate limits — and Delta Exchange is no exception. Rate limits protect the exchange infrastructure from being overwhelmed by excessive requests, whether from overly aggressive trading bots or accidental infinite loops in someone's script. Without these guardrails, a single malfunctioning bot could degrade performance for thousands of traders.
The Delta Exchange API rate limit works on a token bucket model. You get a fixed number of request tokens that refill over time. Once you burn through your allocation, the API returns HTTP 429 (Too Many Requests) and your bot is temporarily locked out. For anyone running automated strategies — whether on Delta Exchange, Binance, or Bybit — understanding these mechanics is the difference between a bot that prints money and one that misses every entry.
The exchange message rate limit applies not just to REST endpoints but also to WebSocket connections. Delta Exchange caps the number of messages you can send per second over WebSocket channels, which matters if you're subscribing to multiple orderbook feeds or sending rapid-fire order updates. Platforms like OKX and Bitget implement similar tiered systems, but each has its own nuances.
Delta Exchange organizes its API rate limits into several categories. Understanding each one helps you architect your bot to stay well within boundaries while still executing efficiently.
| Endpoint Category | Rate Limit | Window |
|---|---|---|
| REST API (General) | 100 requests | 10 seconds |
| Order Placement | 50 requests | 10 seconds |
| Order Cancellation | 50 requests | 10 seconds |
| WebSocket Messages | 20 messages | 1 second |
| Market Data (Public) | 200 requests | 10 seconds |
These limits are per API key, not per IP address. So running multiple bot instances with the same key won't bypass anything — it'll just burn through your quota faster. If you need higher throughput, Delta Exchange offers increased limits for institutional accounts and market makers upon request.
The API rate limit on Delta Exchange resets on a rolling window, not a fixed interval. This means each request starts its own countdown. Plan your request spacing accordingly — bursting 50 orders at once means you'll be locked out for the full window duration.
Before worrying about rate limits, you need proper authentication. Delta Exchange uses HMAC-SHA256 signatures for API authentication. Here's how to set up a basic authenticated client in Python that respects the API rate limit:
import hmac
import hashlib
import time
import requests
import json
class DeltaExchangeClient:
BASE_URL = "https://api.delta.exchange/v2"
def __init__(self, api_key: str, api_secret: str):
self.api_key = api_key
self.api_secret = api_secret
self.session = requests.Session()
self._last_request_time = 0
self._min_interval = 0.12 # ~8 requests/sec to stay under 100/10s
def _generate_signature(self, method: str, endpoint: str, payload: str = "") -> dict:
timestamp = str(int(time.time()))
signature_data = method + timestamp + endpoint + payload
signature = hmac.new(
self.api_secret.encode('utf-8'),
signature_data.encode('utf-8'),
hashlib.sha256
).hexdigest()
return {
"api-key": self.api_key,
"timestamp": timestamp,
"signature": signature,
"Content-Type": "application/json"
}
def _throttle(self):
"""Simple throttle to respect the delta exchange api rate limit."""
elapsed = time.time() - self._last_request_time
if elapsed < self._min_interval:
time.sleep(self._min_interval - elapsed)
self._last_request_time = time.time()
def get_positions(self):
endpoint = "/positions"
self._throttle()
headers = self._generate_signature("GET", endpoint)
response = self.session.get(self.BASE_URL + endpoint, headers=headers)
return response.json()
# Usage
client = DeltaExchangeClient("your_api_key", "your_api_secret")
positions = client.get_positions()
print(json.dumps(positions, indent=2))
The _throttle method is your first line of defense. It enforces a minimum interval between requests so you never accidentally exceed the API rate limit. This approach is simple but effective for single-threaded bots. For more complex setups, you'll need the token bucket pattern shown later.
Even with throttling, you'll eventually hit a 429 response — during high volatility, exchange infrastructure can tighten limits dynamically. The worst thing your bot can do is immediately retry, because that just compounds the problem. Here's a production-grade retry handler with exponential backoff:
import time
import requests
from typing import Optional
def request_with_retry(
session: requests.Session,
method: str,
url: str,
headers: dict,
payload: Optional[dict] = None,
max_retries: int = 5
) -> dict:
"""Make API request with exponential backoff on rate limit errors."""
for attempt in range(max_retries):
if method == "GET":
resp = session.get(url, headers=headers)
else:
resp = session.post(url, headers=headers, json=payload)
if resp.status_code == 200:
return resp.json()
if resp.status_code == 429:
# Check for Retry-After header
retry_after = resp.headers.get("Retry-After")
if retry_after:
wait_time = int(retry_after)
else:
wait_time = min(2 ** attempt, 30) # Cap at 30 seconds
print(f"Rate limited. Waiting {wait_time}s (attempt {attempt + 1})")
time.sleep(wait_time)
continue
if resp.status_code >= 500:
# Server error — brief retry
time.sleep(1)
continue
# Client error (4xx other than 429) — don't retry
resp.raise_for_status()
raise Exception(f"Max retries ({max_retries}) exceeded for {url}")
# Example: fetch orderbook with retry logic
result = request_with_retry(
session=requests.Session(),
method="GET",
url="https://api.delta.exchange/v2/l2orderbook/BTCUSDT",
headers={"Content-Type": "application/json"}
)
print(f"Best bid: {result['result']['buy'][0]['price']}")
Notice how we check the Retry-After header first. Delta Exchange sometimes tells you exactly how long to wait — always respect that value. The exponential backoff (1s, 2s, 4s, 8s...) is your fallback. This same pattern works when you're hitting the API rate limit on Binance or Bybit, though their header names might differ.
If your trading strategy involves multiple concurrent operations — say, monitoring positions while simultaneously placing orders and streaming market data from VoiceOfChain signals — a simple sleep-based throttle won't cut it. You need a proper token bucket implementation that's thread-safe:
class TokenBucketLimiter {
constructor(maxTokens, refillRate, refillInterval) {
this.maxTokens = maxTokens; // e.g., 100 for general endpoints
this.tokens = maxTokens;
this.refillRate = refillRate; // tokens added per interval
this.refillInterval = refillInterval; // in milliseconds
this.lastRefill = Date.now();
}
async waitForToken() {
while (true) {
this._refill();
if (this.tokens >= 1) {
this.tokens -= 1;
return;
}
// Wait a fraction of the refill interval
await new Promise(r => setTimeout(r, this.refillInterval / this.refillRate));
}
}
_refill() {
const now = Date.now();
const elapsed = now - this.lastRefill;
const tokensToAdd = Math.floor(elapsed / this.refillInterval) * this.refillRate;
if (tokensToAdd > 0) {
this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);
this.lastRefill = now;
}
}
}
// Configure for Delta Exchange rate limits
const orderLimiter = new TokenBucketLimiter(50, 50, 10000); // 50 per 10s
const generalLimiter = new TokenBucketLimiter(100, 100, 10000);
async function placeOrder(orderData) {
await orderLimiter.waitForToken();
const response = await fetch('https://api.delta.exchange/v2/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(orderData)
});
return response.json();
}
// Safe to call rapidly — the limiter handles pacing
const orders = [
{ symbol: 'BTCUSDT', size: 1, side: 'buy', order_type: 'limit_order', limit_price: '65000' },
{ symbol: 'ETHUSDT', size: 10, side: 'sell', order_type: 'limit_order', limit_price: '3200' }
];
for (const order of orders) {
placeOrder(order).then(res => console.log('Order placed:', res));
}
This pattern lets you fire off requests from anywhere in your codebase without worrying about exceeding the exchange message rate limit. The limiter queues callers transparently. It's the same approach used by professional quant teams trading across Delta Exchange, KuCoin, and Gate.io simultaneously.
Pro tip: If you're building a bot that trades on both Delta Exchange and Binance, maintain separate rate limiter instances per exchange. Never share a single limiter across different APIs — their limits, windows, and counting methods all differ.