Skip to main content
The Causeloop API enforces a sliding-window rate limit per client IP. All requests — authenticated or not — count against the limit for the originating IP address.

Limits

The limit is applied per IP address (or the first value of X-Forwarded-For when the request passes through a proxy). Requests from different IPs are counted independently.
When Redis is configured (REDIS_URL), the limit is enforced across all API replicas using a shared fixed-window counter. Without Redis, the counter is per-process — a single IP hitting multiple replicas gets a higher effective limit. In production, configure Redis for consistent enforcement.

Rate limit response headers

Every response — including successful ones — carries two rate limit headers: When the limit is exceeded, the 429 response also includes:

429 response body

The 429 error body does not include a trace_id. Use the Retry-After header value, not a fixed delay, to determine how long to wait.

Handling rate limits

Read the X-RateLimit-Remaining header on every response. When it reaches zero or you receive a 429, back off and retry:

Best practices

Read X-RateLimit-Remaining proactively. If it’s low, slow down your request rate before hitting the limit. Implement exponential backoff with jitter. Start at the Retry-After value, then double the delay on each subsequent 429. Add random jitter (±500 ms) to avoid thundering-herd when multiple clients retry in sync. Avoid polling for status. Use the WebSocket stream for real-time updates — WebSocket messages do not count against REST rate limits. For endpoints that do require polling: Batch requests where possible. Filter lists server-side (?status=open) rather than fetching all records and filtering client-side.