Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/KingPsychopath/oooc-fete-finder/llms.txt

Use this file to discover all available pages before exploring further.

Public write and tracking endpoints are protected with in-app Postgres-backed atomic counters. Edge WAF can still be layered for additional protection.

Protected endpoints

The following API endpoints have rate limiting enabled:
  • POST /api/auth/verify - User authentication
  • POST /api/event-submissions - Event submission
  • POST /api/track - Analytics tracking
  • POST /api/track/discovery - Discovery event tracking
  • POST /api/user/preference - User preference updates

Rate limit policies

Authentication endpoint

POST /api/auth/verify
IP limit
60 requests / 60 seconds
Per-IP address rate limit for authentication attempts
Email + IP limit
6 requests / 15 minutes
Combined email and IP address limit to prevent targeted attacks
Block response
429
Returns HTTP 429 with Retry-After header
When the rate limiter is unavailable, authentication requests fail-open (allowed) to maintain service availability.

Event submission endpoint

POST /api/event-submissions
IP limit
20 requests / 10 minutes
Per-IP address limit for event submissions
Email + IP limit
5 requests / 60 minutes
Combined email and IP address limit
Fingerprint limit
1 request / 24 hours
Content-based fingerprint limit to prevent duplicate submissions
Block response
429
Returns HTTP 429 with Retry-After header
When the rate limiter is unavailable, event submissions fail-closed (503 Service Unavailable) to prevent abuse.

Tracking endpoints

POST /api/track
IP limit
240 requests / 60 seconds
Per-IP address limit for general tracking events
Session limit
200 requests / 60 seconds
Per-session limit for tracking events
On limiter failure or block, the endpoint returns 202 Accepted without recording the event.
POST /api/track/discovery
IP limit
180 requests / 60 seconds
Per-IP address limit for discovery tracking
Session limit
150 requests / 60 seconds
Per-session limit for discovery tracking
On limiter failure or block, the endpoint returns 202 Accepted without recording the event.

User preference endpoint

POST /api/user/preference
IP limit
120 requests / 60 seconds
Per-IP address limit for preference updates
Invalid or unauthenticated requests are accepted as no-ops with 202 status.

Implementation details

Counter storage

Rate limit counters are stored in the app_rate_limit_counters table with atomic increment operations to ensure accuracy under concurrent load.

IP extraction

Client IP addresses are extracted from request headers in the following order:
  1. x-forwarded-for (first IP in the list)
  2. x-real-ip
  3. Falls back to “unknown” if neither header is present
See extractClientIpFromHeaders in features/security/rate-limiter.ts:56.

Privacy protection

Limiter keys are HMAC-hashed using AUTH_SECRET before storage. Raw IP addresses and email addresses are never persisted in the rate limit counter table.
The key hash is generated using:
createHmac('sha256', env.AUTH_SECRET)
  .update(parts.join('|'))
  .digest('hex')
See buildRateLimitKeyHash in features/security/rate-limiter.ts:75.

Cleanup

Expired rate limit counters are automatically cleaned up via a scheduled cron job:
Endpoint
GET /api/cron/cleanup-rate-limits
Cron endpoint for cleaning up expired counters
Authentication
Authorization: Bearer <CRON_SECRET>
Requires CRON_SECRET environment variable for authentication
Behavior
Deletes expired counters with grace window
Removes counters that have expired beyond a 24-hour grace period

Failover behavior

Different endpoints have different failover strategies when the rate limiter is unavailable:
EndpointBehavior
/api/auth/verifyFail-open (allow request)
/api/event-submissionsFail-closed (return 503)
/api/trackAccept with 202 (don’t record)
/api/track/discoveryAccept with 202 (don’t record)
/api/user/preferenceAllow request
Event submissions use fail-closed behavior to prevent spam when the rate limiter is down. All other endpoints prioritize availability.