Nudg3Docs

Rate Limits

Understand rate limiting policies for the Nudg3 API

Rate Limits

The Nudg3 API implements rate limiting to ensure fair usage and platform stability. Rate limits are applied per API key and vary by subscription tier.

Rate Limit Tiers

TierPer MinutePer HourPer Day
Basic606005,000
Premium3003,00050,000

Export endpoints have additional limits: 10 exports per hour regardless of tier.

Rate Limit Algorithm

Nudg3 uses a sliding window counter algorithm with Redis backing. This provides:

  • Smooth rate limiting without hard cutoffs at window boundaries
  • Accurate counting across distributed systems
  • Fail-open behavior (requests allowed if Redis is temporarily unavailable)

Response Headers

All API responses include rate limit headers:

X-RateLimit-Limit-Minute: 60
X-RateLimit-Remaining-Minute: 45
X-RateLimit-Reset-Minute: 2026-01-12T10:31:00Z

X-RateLimit-Limit-Hour: 600
X-RateLimit-Remaining-Hour: 520
X-RateLimit-Reset-Hour: 2026-01-12T11:00:00Z

X-RateLimit-Limit-Day: 5000
X-RateLimit-Remaining-Day: 4800
X-RateLimit-Reset-Day: 2026-01-13T00:00:00Z
HeaderDescription
X-RateLimit-Limit-*Maximum requests allowed in the window
X-RateLimit-Remaining-*Requests remaining in the current window
X-RateLimit-Reset-*ISO 8601 timestamp when the window resets

Rate Limit Exceeded

When you exceed the rate limit, the API returns a 429 Too Many Requests response:

{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Try again in 45 seconds.",
    "retry_after": 45
  }
}

The response includes a Retry-After header with the number of seconds to wait:

HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Remaining-Minute: 0
X-RateLimit-Reset-Minute: 2026-01-12T10:31:00Z

Best Practices

Implement Exponential Backoff

When receiving a 429 response, implement exponential backoff:

async function apiCallWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);
 
    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
      const backoff = Math.min(retryAfter * Math.pow(2, attempt), 300);
      await new Promise(resolve => setTimeout(resolve, backoff * 1000));
      continue;
    }
 
    return response;
  }
  throw new Error('Max retries exceeded');
}

Monitor Rate Limit Headers

Check headers proactively to avoid hitting limits:

function checkRateLimits(response) {
  const remaining = parseInt(response.headers.get('X-RateLimit-Remaining-Minute'));
  const limit = parseInt(response.headers.get('X-RateLimit-Limit-Minute'));
 
  if (remaining < limit * 0.1) {
    console.warn('Approaching rate limit:', remaining, 'requests remaining');
  }
}

Batch Requests

Instead of making many small requests, batch your operations:

// Instead of this (3 requests):
await api.getBrand('brand1');
await api.getBrand('brand2');
await api.getBrand('brand3');
 
// Use this (1 request):
await api.getBrands({ ids: ['brand1', 'brand2', 'brand3'] });

Cache Responses

Cache API responses to reduce request volume:

const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
 
async function getCachedDashboard(filters) {
  const key = JSON.stringify(filters);
  const cached = cache.get(key);
 
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
 
  const data = await api.getDashboard(filters);
  cache.set(key, { data, timestamp: Date.now() });
  return data;
}

Export Rate Limits

Export endpoints have stricter limits due to their resource-intensive nature:

LimitValueBehavior
Exports per hour10Strict, fail-closed
Concurrent exports1Additional exports queued
Max rows per export1,000,000Large exports split automatically

Unlike other endpoints, export rate limits use fail-closed behavior. If Redis is unavailable, export requests are rejected.

Pre-Download Estimation

Before downloading large exports, check the statistics endpoint:

curl "https://api.nudg3.ai/api/v1/exports/chat-responses/statistics" \
  -H "Authorization: Bearer nudg3_live_ak_your_key"
{
  "success": true,
  "data": {
    "total_rows": 150000,
    "estimated_size_mb": 45.2
  }
}

If the export is large, consider using date filters to break it into smaller chunks.

Brute Force Protection

The API includes brute force protection for invalid API keys:

ThresholdAction
10 failed authenticationsIP blocked for 1 hour
Repeated blocksProgressive blocking periods

This protection prevents credential stuffing attacks while allowing legitimate users to recover from typos.

Requesting Higher Limits

If you need higher rate limits:

  1. Review your usage patterns for optimization opportunities
  2. Contact sales to discuss Premium tier upgrade
  3. For enterprise needs, custom limits are available

Next Steps

On this page