Rate Limiting Guide
The mCards API enforces rate limits to ensure fair usage and platform stability. This guide explains how rate limits work and how to handle them.
Rate Limit Tiers
| Endpoint | Limit | Window |
|---|---|---|
| Standard API endpoints | 120 requests | Per minute |
Token endpoint (POST /oauth/token) | 20 requests | Per minute |
| Sandbox simulation endpoints | 60 requests | Per minute |
Rate limits are applied per API key (HMAC) or per OAuth application (Bearer token).
Response Headers
Every API response includes rate limit headers:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit | Maximum requests per window | 120 |
X-RateLimit-Remaining | Requests remaining | 117 |
X-RateLimit-Reset | Unix timestamp when window resets | 1710000060 |
Handling Rate Limits
When you exceed the rate limit, the API returns 429 Too Many Requests:
json
{
"error": "Rate limit exceeded",
"retry_after": 45
}TypeScript Example
typescript
async function fetchWithRetry(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const result = await fn();
if (result.status === 429) {
const retryAfter = result.headers?.['retry-after'] || 60;
console.log(\`Rate limited. Retrying in \${retryAfter}s...\`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return result;
}
throw new Error('Max retries exceeded');
}
const wallets = await fetchWithRetry(() => client.wallets.list());Python Example
python
import time
def fetch_with_retry(fn, max_retries=3):
for attempt in range(max_retries):
result = fn()
if result.status == 429:
retry_after = int(result.headers.get("Retry-After", 60))
print(f"Rate limited. Retrying in {retry_after}s...")
time.sleep(retry_after)
continue
return result
raise RuntimeError("Max retries exceeded")
wallets = fetch_with_retry(lambda: client.wallets.list())Proactive Rate Limit Monitoring
Check your current usage without consuming a rate limit slot:
bash
GET /api/v2/oauth/rate_limitjson
{
"rate_limit": {
"limit": 120,
"used": 45,
"remaining": 75,
"reset_at": "2026-03-12T10:31:00Z",
"window_seconds": 60
}
}Best Practices
- Implement exponential backoff — do not retry immediately on 429
- Monitor rate limit headers — track
X-RateLimit-Remaining - Batch operations — use list endpoints with pagination instead of individual fetches
- Cache responses — reduce API calls by caching stable data
- Use webhooks — subscribe to events instead of polling
- Contact support — if you need higher limits, email developers@mcards.com