Rate Limits
REST and public WebSocket rate limit tiers plus API key authentication for higher REST limits
Diffusal enforces rate limits on REST and public WebSocket endpoints to protect the platform and ensure fair usage. Authenticated users with API keys receive higher limits on supported REST flows based on their tier.
Tier System
REST rate limits are tiered based on authentication status and trading volume.
| Tier | Criteria | Orders/min | Data/min |
|---|---|---|---|
| Unauthenticated | No API key (IP-based) | — | 600 |
| Tier 1 | Authenticated trader | 600 | 300 |
| Tier 2 | ≥ $100k 30-day volume | 1,200 | 600 |
| Tier 3 | ≥ $1M 30-day volume | 2,400 | 1,000 |
Column definitions:
- Orders/min — Rate limit for trading and account mutation endpoints (
/api/mm/*,/api/portfolio/*,/api/strategies/*,/api/rfq/*) - Data/min — Rate limit for market data endpoints (
/api/markets/*)
REST Rate Limits
Public Market Data Endpoints
Public endpoints like /api/markets/pairs, /api/markets/ticker/:symbol, and /api/markets/orderbook/:symbol are rate-limited by IP at 600 requests/min for unauthenticated users.
To receive higher limits on public endpoints, include your API key headers in the request. The server will resolve your tier and apply the corresponding Data/min limit instead:
curl https://api.testnet.diffusal.xyz/api/markets/pairs \
-H "X-API-Key: dfsl_your_key_id" \
-H "X-API-Timestamp: $(date +%s%3N)" \
-H "X-API-Signature: your_hmac_signature"If the API key headers are present but invalid (expired, wrong signature, revoked key), the request falls back to IP-based limits silently — it does not return a 401 error. This matches the behavior of major exchanges.
Authenticated Endpoints
Endpoints requiring authentication (/api/mm/*, /api/portfolio/*, /api/strategies/*, /api/rfq/*, /api/account/*) use the Orders/min limit keyed by your API key or wallet address.
Rate Limit Response Headers
Authenticated requests include rate limit headers in the response:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 595
X-RateLimit-Reset: 1709827200HTTP 429 Responses
When a rate limit is exceeded, the server returns:
HTTP/1.1 429 Too Many Requests
{
"code": "resource_exhausted",
"message": "rate limit exceeded"
}WebSocket Rate Limits
Current public WebSocket limits:
| Limit | Public value |
|---|---|
| Connections/min | 10 |
| Messages/min | 60 |
| Max subscriptions | 25 |
Connection Rate Limit
New public WebSocket connections are rate-limited per IP. If you exceed the connection limit, the connection is silently closed.
Message Rate Limit
Inbound messages on an active public WebSocket connection are rate-limited. If you exceed the message limit, the server responds with an error but keeps the connection open:
{
"error": {
"code": 4029,
"msg": "message rate limit exceeded"
},
"id": 0
}Your client can back off and resume sending messages after the window resets (60 seconds).
Subscription Limit
Each public WebSocket connection has a maximum number of concurrent subscriptions. Attempting to subscribe beyond the limit returns:
{
"error": {
"code": 4029,
"msg": "subscription limit exceeded (max 25)"
},
"id": 1
}The public docs route documents only the public websocket surface. Contributor-only realtime authentication and any non-public websocket tiers are intentionally omitted here.
API Keys
Creating an API Key
API keys are created through the dashboard or the REST API. You must be authenticated with a SIWE session first.
# Create a new API key with trade + read scopes
curl -X POST https://api.testnet.diffusal.xyz/api/keys \
-H "Authorization: Bearer your_session_token" \
-H "Content-Type: application/json" \
-d '{"label": "Trading Bot", "scopes": ["read", "trade"]}'Response:
{
"keyId": "dfsl_abc123...",
"secret": "hex_encoded_secret...",
"label": "Trading Bot",
"scopes": ["read", "trade"]
}Important: The secret is only returned once at creation time. Store it securely.
Managing API Keys
| Endpoint | Method | Description |
|---|---|---|
/api/keys | POST | Create a new scoped API key |
/api/keys | GET | List active API keys |
/api/keys/:keyId | DELETE | Revoke an API key |
/api/keys/:keyId/rotate | POST | Rotate an API key secret |
Authenticating with API Keys
Include these three headers in every authenticated request:
| Header | Description |
|---|---|
X-API-Key | Your key ID (e.g. dfsl_abc123...) |
X-API-Timestamp | Current time in milliseconds since epoch |
X-API-Signature | HMAC-SHA256 of the timestamp using your secret |
Generating the signature:
import { createHmac } from "crypto";
const timestamp = Date.now().toString();
const signature = createHmac("sha256", apiSecret)
.update(timestamp)
.digest("hex");import hmac, hashlib, time
timestamp = str(int(time.time() * 1000))
signature = hmac.new(
api_secret.encode(), timestamp.encode(), hashlib.sha256
).hexdigest()The timestamp must be within 30 seconds of the server's current time.
Available Scopes
| Scope | Access |
|---|---|
read | Read account data, positions, balances |
trade | Place and cancel orders, execute RFQ fills |
withdraw | Withdraw collateral |
Dashboard
The Diffusal dashboard provides a visual interface for API key management:
- Connect wallet — Sign in with your wallet using SIWE
- Navigate to Settings → API Keys — View and manage your keys
- Create Key — Select scopes and generate a new key pair
- Copy Secret — Save the secret immediately (shown only once)
- Revoke/Rotate — Revoke compromised keys or rotate secrets
The dashboard also displays your current rate limit tier, 30-day trading volume, and real-time usage metrics.