* Initial plan * docs: add comprehensive contributing guidelines and templates Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * docs: update README and SECURITY with better formatting and links Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * docs: finalize contributing guidelines and formatting Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com>
18 KiB
Rate Limiting & DDoS Protection API Documentation
Overview
This document describes the rate limiting, DDoS protection, and IP management features of the Discord SpyWatcher API.
Rate Limiting
Rate Limit Headers
All API responses include the following rate limit headers:
X-RateLimit-Limit: Maximum number of requests allowed in the time windowX-RateLimit-Remaining: Number of requests remaining in the current windowX-RateLimit-Reset: Timestamp when the rate limit window resetsRetry-After: (when rate limited) Seconds until the client can retry
Rate Limit Policies
| Endpoint Category | Limit | Window | Description |
|---|---|---|---|
| Global | 100 requests | 15 minutes | Applied to all API endpoints |
| Authentication | 5 requests | 15 minutes | Login and authentication endpoints |
| Analytics | 30 requests | 1 minute | Analytics data endpoints |
| Admin | 100 requests | 15 minutes | Admin-only endpoints |
| Public | 60 requests | 1 minute | Public data endpoints |
| Webhooks | 1000 requests | 1 hour | Webhook endpoints |
| Refresh Token | 10 requests | 15 minutes | Token refresh endpoint |
User-Based Rate Limiting
Authenticated users have different rate limits based on their subscription tier and role:
By Subscription Tier:
- FREE: 30 requests/minute, 100 requests/15 minutes
- PRO: 100 requests/minute, 1,000 requests/15 minutes
- ENTERPRISE: 300 requests/minute, 5,000 requests/15 minutes
By Role (overrides tier limits):
- Admin: 200 requests/minute
- Moderator: 100 requests/minute
- Unauthenticated: 30 requests/minute
Rate Limit Response
When rate limited, the API returns a 429 Too Many Requests response:
{
"error": "Too many requests",
"message": "Too many requests. Please try again later.",
"retryAfter": 600
}
Quota Management
Overview
In addition to rate limiting, the API implements a quota system that tracks daily request limits based on subscription tiers. Quotas are tracked per endpoint category and reset daily at midnight UTC.
Quota Headers
All authenticated API responses include quota-related headers:
X-Quota-Limit: Maximum number of requests allowed per day for this categoryX-Quota-Remaining: Number of requests remaining in the current dayX-Quota-Reset: Seconds until quota resets (at midnight UTC)X-Quota-Category: Endpoint category (analytics, api, admin, public)
Subscription Tiers
FREE Tier
| Category | Daily Limit |
|---|---|
| Analytics | 100 requests |
| API | 1,000 requests |
| Public | 500 requests |
| Admin | No access |
| Total | 1,000 requests |
PRO Tier
| Category | Daily Limit |
|---|---|
| Analytics | 1,000 requests |
| API | 10,000 requests |
| Public | 5,000 requests |
| Admin | No access |
| Total | 10,000 requests |
ENTERPRISE Tier
| Category | Daily Limit |
|---|---|
| Analytics | 10,000 requests |
| API | 100,000 requests |
| Public | 50,000 requests |
| Admin | 50,000 requests |
| Total | 100,000 requests |
Endpoint Categories
Quotas are tracked by endpoint category:
- Analytics:
/api/analytics/*- Data and statistics endpoints - Admin:
/api/admin/*- Administrative endpoints - Public:
/api/public/*- Public API endpoints - API: All other
/api/*endpoints
Quota Exceeded Response
When quota is exceeded, the API returns a 429 Too Many Requests response:
{
"error": "Quota exceeded",
"message": "You have exceeded your analytics quota for the day. Please upgrade your subscription or try again tomorrow.",
"quota": {
"limit": 100,
"remaining": 0,
"reset": 43200,
"category": "analytics"
}
}
Quota Management Endpoints
Get Personal Quota Usage
View your current quota usage across all categories.
Endpoint: GET /api/quota/usage
Authentication: Required (JWT or API key)
Response:
{
"tier": "FREE",
"usage": {
"analytics": {
"used": 50,
"limit": 100,
"remaining": 50
},
"api": {
"used": 200,
"limit": 1000,
"remaining": 800
},
"total": {
"used": 250,
"limit": 1000,
"remaining": 750
}
},
"limits": {
"analytics": { "requests": 100, "window": "daily" },
"api": { "requests": 1000, "window": "daily" },
"total": { "requests": 1000, "window": "daily" }
},
"rateLimits": {
"requestsPerMinute": 30,
"requestsPer15Minutes": 100
}
}
Get All Tier Limits
View quota and rate limits for all subscription tiers.
Endpoint: GET /api/quota/limits
Authentication: None required
Response:
{
"FREE": {
"quotas": {
"analytics": { "requests": 100, "window": "daily" },
"api": { "requests": 1000, "window": "daily" },
"total": { "requests": 1000, "window": "daily" }
},
"rateLimits": {
"requestsPerMinute": 30,
"requestsPer15Minutes": 100
}
},
"PRO": {
"quotas": { ... },
"rateLimits": { ... }
},
"ENTERPRISE": {
"quotas": { ... },
"rateLimits": { ... }
}
}
Get User Quota Usage (Admin Only)
View quota usage for a specific user.
Endpoint: GET /api/quota/users/:userId
Authentication: Required (Admin role)
Response:
{
"user": {
"id": "user123",
"username": "johndoe",
"tier": "PRO",
"role": "USER"
},
"usage": {
"analytics": {
"used": 500,
"limit": 1000,
"remaining": 500
},
"total": {
"used": 5000,
"limit": 10000,
"remaining": 5000
}
},
"limits": { ... }
}
Update User Subscription Tier (Admin Only)
Change a user's subscription tier.
Endpoint: PUT /api/quota/users/:userId/tier
Authentication: Required (Admin role)
Request Body:
{
"tier": "PRO"
}
Response:
{
"message": "User tier updated successfully",
"user": {
"id": "user123",
"username": "johndoe",
"subscriptionTier": "PRO"
}
}
Reset User Quota (Admin Only)
Reset quota usage for a user. Optionally specify a category to reset only that category.
Endpoint: DELETE /api/quota/users/:userId/reset?category=analytics
Authentication: Required (Admin role)
Query Parameters:
category(optional): Specific category to reset (analytics, api, admin, public, total)
Response:
{
"message": "Quota reset for category: analytics",
"userId": "user123",
"username": "johndoe",
"category": "analytics"
}
Quota Tracking
- Quotas are tracked in Redis for fast access
- Counters automatically expire at midnight UTC
- Both category-specific and total quotas are enforced
- Only successful requests (status < 400) count against quotas
IP Management
Prerequisites
All IP management endpoints require:
- Authentication (valid JWT token)
- Admin role
Base URL: /api/admin/ip-management
List Blocked IPs
Get all permanently blocked IP addresses.
Endpoint: GET /blocked
Response:
{
"blocked": [
{
"ip": "192.168.1.1",
"reason": "Malicious activity",
"createdAt": "2024-01-01T00:00:00.000Z"
}
]
}
List Whitelisted IPs
Get all whitelisted IP addresses.
Endpoint: GET /whitelisted
Response:
{
"whitelisted": [
{
"ip": "192.168.1.100",
"reason": "Office IP",
"createdAt": "2024-01-01T00:00:00.000Z"
}
]
}
Check IP Status
Check the blocking/whitelisting status of a specific IP.
Endpoint: GET /check/:ip
Parameters:
ip(path): IP address to check (IPv4 or IPv6)
Response:
{
"ip": "192.168.1.1",
"blocked": false,
"whitelisted": false,
"violations": 5,
"status": "normal"
}
Status Values:
normal: IP is neither blocked nor whitelistedblocked: IP is permanently blockedwhitelisted: IP is whitelisted
Block IP Permanently
Permanently block an IP address.
Endpoint: POST /block
Request Body:
{
"ip": "192.168.1.1",
"reason": "Malicious activity detected"
}
Response:
{
"message": "IP permanently blocked",
"ip": "192.168.1.1",
"reason": "Malicious activity detected"
}
Block IP Temporarily
Temporarily block an IP address for a specified duration.
Endpoint: POST /temp-block
Request Body:
{
"ip": "192.168.1.1",
"duration": 3600,
"reason": "Rate limit abuse"
}
Parameters:
ip: IP address to blockduration: Block duration in seconds (60-86400)reason: (optional) Reason for blocking
Response:
{
"message": "IP temporarily blocked",
"ip": "192.168.1.1",
"duration": 3600,
"reason": "Rate limit abuse"
}
Unblock IP
Remove a permanent IP block.
Endpoint: DELETE /unblock/:ip
Parameters:
ip(path): IP address to unblock
Response:
{
"message": "IP unblocked successfully",
"ip": "192.168.1.1"
}
Remove Temporary Block
Remove a temporary IP block.
Endpoint: DELETE /temp-unblock/:ip
Parameters:
ip(path): IP address to unblock
Response:
{
"message": "Temporary block removed successfully",
"ip": "192.168.1.1"
}
Add IP to Whitelist
Add an IP to the whitelist, bypassing all rate limits and blocks.
Endpoint: POST /whitelist
Request Body:
{
"ip": "192.168.1.100",
"reason": "Office IP address"
}
Response:
{
"message": "IP added to whitelist",
"ip": "192.168.1.100",
"reason": "Office IP address"
}
Remove IP from Whitelist
Remove an IP from the whitelist.
Endpoint: DELETE /whitelist/:ip
Parameters:
ip(path): IP address to remove from whitelist
Response:
{
"message": "IP removed from whitelist",
"ip": "192.168.1.100"
}
Monitoring
Prerequisites
All monitoring endpoints require:
- Authentication (valid JWT token)
- Admin role
Base URL: /api/admin/monitoring
Rate Limit Statistics
Get overall rate limit statistics and violations.
Endpoint: GET /rate-limits
Response:
{
"violations": [
{
"ip": "192.168.1.1",
"count": 15,
"ttl": 3456
}
],
"tempBlocked": [
{
"ip": "192.168.1.2",
"ttl": 1800
}
],
"rateLimitStats": {
"global": 45,
"auth": 12,
"analytics": 8
},
"summary": {
"totalViolations": 27,
"uniqueIPsWithViolations": 5,
"tempBlockedCount": 2,
"activeRateLimiters": 3
}
}
IP Rate Limit Details
Get detailed rate limit information for a specific IP.
Endpoint: GET /rate-limits/:ip
Parameters:
ip(path): IP address to check
Response:
{
"ip": "192.168.1.1",
"violations": 15,
"violationTTL": 3456,
"isTemporarilyBlocked": false,
"blockTTL": null,
"rateLimitInfo": {
"rl:global:192.168.1.1": {
"value": "45",
"ttl": 854
}
}
}
Clear Rate Limit Data
Clear rate limit violations and data for a specific IP.
Endpoint: DELETE /rate-limits/:ip
Parameters:
ip(path): IP address to clear data for
Response:
{
"message": "Rate limit data cleared successfully",
"ip": "192.168.1.1",
"clearedKeys": 3
}
System Health
Get system health and performance metrics.
Endpoint: GET /system
Response:
{
"status": "healthy",
"timestamp": "2024-01-01T00:00:00.000Z",
"uptime": "86400s",
"system": {
"cpu": {
"usage": "45.2%",
"cores": 4,
"load": [0.8, 0.7, 0.6]
},
"memory": {
"usage": "62.3%",
"free": "2048MB",
"total": "8192MB"
},
"process": {
"memory": {
"rss": 125829120,
"heapTotal": 67584000,
"heapUsed": 45678912,
"external": 1234567
},
"pid": 12345
}
},
"redis": {
"available": true
}
}
DDoS Protection
Automatic Protection Features
The API automatically protects against various DDoS attack vectors:
Layer 7 Protection
- Request Validation: Malformed requests are rejected
- Payload Size Limits: Maximum 10MB per request
- Query Parameter Limits: Maximum 30 parameters per request
- Header Validation: Excessive or malicious headers are rejected
- Slow Request Detection: Requests taking >30s are terminated
Intelligent Blocking
- Automatic IP Blocking: IPs with 10+ rate limit violations are auto-blocked for 1 hour
- Progressive Delays: Requests beyond limits incur increasing delays (up to 20s)
- Abuse Detection: Suspicious patterns trigger automatic countermeasures
Load Management
- Circuit Breaker: Fails fast after 5 consecutive errors, recovers after 1 minute
- Load Shedding: Under heavy load (CPU >80% or Memory >90%), non-critical requests are rejected
- Priority Queuing: Admin requests are prioritized during high load
Cache Headers
The API uses cache headers to reduce load:
- Analytics:
Cache-Control: private, max-age=60 - GET Requests:
Cache-Control: private, max-age=30 - Health Checks:
Cache-Control: no-cache, no-store - Mutations:
Cache-Control: no-cache, no-store
ETags
The API supports ETags for conditional requests. Include If-None-Match header with the ETag value to receive a 304 Not Modified response when content hasn't changed.
Error Responses
400 Bad Request
Invalid request format or parameters.
{
"error": "Invalid IP address format"
}
403 Forbidden
IP address is blocked.
{
"error": "Access denied from this IP",
"reason": "IP address permanently blocked"
}
413 Payload Too Large
Request exceeds size limit.
{
"error": "Request entity too large",
"maxSize": "10MB",
"received": "15.2MB"
}
429 Too Many Requests
Rate limit exceeded.
{
"error": "Too many requests",
"message": "Too many authentication attempts. Please try again later.",
"retryAfter": 600
}
503 Service Unavailable
Service temporarily unavailable due to high load or maintenance.
{
"error": "Service temporarily unavailable",
"message": "Server under high load, please try again later",
"retryAfter": 60
}
Best Practices
For API Consumers
- Monitor Headers: Check both rate limit (
X-RateLimit-*) and quota (X-Quota-*) headers - Track Quota Usage: Regularly check
/api/quota/usageto monitor your daily consumption - Implement Exponential Backoff: When rate limited or quota exceeded, wait before retrying
- Use Caching: Leverage ETags and Cache-Control headers to reduce API calls
- Handle 429 Gracefully: Don't retry immediately when rate limited or quota exceeded
- Plan for Limits: Design your application around your tier's quota limits
- Upgrade When Needed: Monitor usage patterns and upgrade tier if approaching limits
- Distribute Load: Spread requests throughout the day to avoid hitting rate limits
For Administrators
- Monitor Violations: Regularly check
/api/admin/monitoring/rate-limits - Track User Quotas: Use
/api/quota/users/:userIdto monitor high-volume users - Manage Tiers: Assign appropriate subscription tiers based on user needs
- Reset Quotas: Use quota reset sparingly and only when justified
- Whitelist Trusted IPs: Add office/server IPs to whitelist
- Review Blocked IPs: Periodically review and clean up blocks
- Set Up Alerts: Monitor system health via
/api/admin/monitoring/system - Document Changes: Always provide a reason when blocking IPs or changing tiers
- Analyze Usage: Review quota usage patterns to identify optimization opportunities
Configuration
Rate limiting and DDoS protection can be configured via environment variables:
# Enable/disable rate limiting
ENABLE_RATE_LIMITING=true
# Enable/disable IP blocking
ENABLE_IP_BLOCKING=true
# Enable/disable Redis-backed rate limiting
ENABLE_REDIS_RATE_LIMITING=true
# Enable/disable load shedding
ENABLE_LOAD_SHEDDING=true
# Redis connection URL (optional)
REDIS_URL=redis://localhost:6379
# Maximum request size in MB
MAX_REQUEST_SIZE_MB=10
Database Schema
BlockedIP Model
model BlockedIP {
id Int @id @default(autoincrement())
ip String @unique
reason String?
createdAt DateTime @default(now())
}
WhitelistedIP Model
model WhitelistedIP {
id Int @id @default(autoincrement())
ip String @unique
reason String?
createdAt DateTime @default(now())
}
Support
For issues or questions about rate limiting and DDoS protection, please refer to:
- SECURITY.md - Security policies
- GitHub Issues - Report issues
- Contributing Guide - Contribution guidelines