Rate Limiting
All API endpoints are rate-limited to prevent abuse and ensure fair access. Limits are enforced per client IP address and endpoint path using Redis.
How It Worksβ
- Each endpoint has a configured maximum number of requests per 1 minute window
- Limits are tracked per client IP + normalized endpoint path combination
- Path parameters are normalized (e.g.,
/users/123becomes/users/:id) - When a limit is exceeded, the API returns
429 Too Many Requests - If Redis is unavailable, rate limiting degrades gracefully (requests are allowed)
Response Headersβ
Every API response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per minute |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Milliseconds until the window resets |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
Rate Limits by Endpointβ
Authenticationβ
| Endpoint | Method | Limit |
|---|---|---|
/auth/sign-up | POST | 5/min |
/auth/sign-in | POST | 10/min |
/auth/verify-email | POST | 5/min |
/auth/forgot-password | POST | 5/min |
/auth/reset-password | POST | 5/min |
/auth/google, /github, /vk, /yandex | GET | 10/min |
/auth/*/callback | GET | 20/min |
/auth/logout | DELETE | 20/min |
/auth/refresh | POST | 30/min |
/auth/me | GET | 60/min |
Usersβ
| Endpoint | Method | Limit |
|---|---|---|
/users/me/withdraw | POST | 5/min |
/users/me/avatar | POST/DELETE | 10/min |
/users/me | PUT | 20/min |
/users/me/referral/* | GET | 30/min |
/users/me/watchlist/{id} | POST/DELETE | 30/min |
/users/* (read) | GET | 60/min |
/users/me/watchlist | GET | 60/min |
/users/me/pnl/chart | GET | 60/min |
Eventsβ
| Endpoint | Method | Limit |
|---|---|---|
/events/{id} | DELETE | 5/min |
/events | POST | 10/min |
/events/{id}/image | POST/DELETE | 10/min |
/events/{id} | PUT | 20/min |
/search_events | GET | 60/min |
/events, /events/feed, /events/{id} | GET | 120/min |
Poolsβ
| Endpoint | Method | Limit |
|---|---|---|
/events/{id}/pools | POST | 10/min |
/pools/{id}/ratio/chart | GET | 60/min |
/pools/batch, /pools/{id} | GET | 120/min |
Trading (Orderbook)β
| Endpoint | Method | Limit |
|---|---|---|
/market/orders | POST | 30/min |
/market/orders/{id} | DELETE | 30/min |
/market/orders/my, /market/orders/my/current | GET | 60/min |
/market/positions/my, /market/positions/completed | GET | 60/min |
Trading (LMSR / AMM)β
| Endpoint | Method | Limit |
|---|---|---|
/lmsr/trade | POST | 30/min |
/lmsr/preview | GET | 60/min |
P2P Exchangeβ
| Endpoint | Method | Limit |
|---|---|---|
/p2p/orders, /p2p/orders/{id} | ALL | 120/min |
Notificationsβ
| Endpoint | Method | Limit |
|---|---|---|
/notifications/read-all | PUT | 10/min |
/notifications/{id}/read | PUT | 30/min |
/notifications/{id} | DELETE | 30/min |
/notifications, /notifications/unread, /notifications/unread/count | GET | 60/min |
Commentsβ
| Endpoint | Method | Limit |
|---|---|---|
/comments/{id} | PUT/DELETE | 20/min |
/comments/{id}/reaction | DELETE | 30/min |
/events/{id}/comments | POST | 30/min |
/comments/{id}/reply | POST | 30/min |
/comments/{id}/like, /comments/{id}/dislike | POST | 60/min |
/events/{id}/comments, /comments/{id}/replies | GET | 120/min |
Otherβ
| Endpoint | Method | Limit |
|---|---|---|
/currency/rate | GET | 120/min |
/ws/trades | GET | 480/min |
| All unknown endpoints | ANY | 30/min |
429 Responseβ
When rate limited, the API returns:
{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Please try again later."
}
}
HTTP Status: 429 Too Many Requests
Client IP Detectionβ
The server determines client IP in this priority order:
CF-Connecting-IPheader (Cloudflare β trusted)RemoteAddr(direct connection, port stripped)
X-Forwarded-For and X-Real-IP are not used to prevent IP spoofing.
Best Practicesβ
- Respect
Retry-Afterheaders when receiving 429 responses - Implement exponential backoff for retries
- Cache responses where possible to reduce request frequency
- Use WebSocket feeds for real-time data instead of polling