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

EndpointLimitWindow
Standard API endpoints120 requestsPer minute
Token endpoint (POST /oauth/token)20 requestsPer minute
Sandbox simulation endpoints60 requestsPer minute

Rate limits are applied per API key (HMAC) or per OAuth application (Bearer token).

Response Headers

Every API response includes rate limit headers:

HeaderDescriptionExample
X-RateLimit-LimitMaximum requests per window120
X-RateLimit-RemainingRequests remaining117
X-RateLimit-ResetUnix timestamp when window resets1710000060

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_limit
json
{
  "rate_limit": {
    "limit": 120,
    "used": 45,
    "remaining": 75,
    "reset_at": "2026-03-12T10:31:00Z",
    "window_seconds": 60
  }
}

Best Practices

  1. Implement exponential backoff — do not retry immediately on 429
  2. Monitor rate limit headers — track X-RateLimit-Remaining
  3. Batch operations — use list endpoints with pagination instead of individual fetches
  4. Cache responses — reduce API calls by caching stable data
  5. Use webhooks — subscribe to events instead of polling
  6. Contact support — if you need higher limits, email developers@mcards.com