StreamPay API implements rate limiting to protect against abuse, scraping, and DoS attacks.
| Endpoint Type | Limit | Window |
|---|---|---|
| Read (GET) | 60 requests | 1 minute |
| Write (POST/DELETE) | 10 requests | 1 minute |
When determining rate limits, the API identifies clients in the following priority order:
- API Key (
X-API-Keyheader) - Highest priority - Wallet (JWT Bearer token
subclaim) - For authenticated requests - IP Address (
X-Forwarded-FororX-Real-IPheader) - Fallback
If your infrastructure uses shared NAT, multiple legitimate users may appear to share the same IP address. This could cause rate limits to trigger unexpectedly. Consider:
- Using API keys for server-to-server calls
- Using wallet authentication for user-level tracking
- Contacting support if you need higher limits for NAT-heavy environments
When a rate limit is exceeded, the API returns a 429 Too Many Requests response:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please try again later."
}
}The response includes a Retry-After header indicating when you can retry:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
All API endpoints are rate limited:
| Method | Endpoint | Limit Type |
|---|---|---|
| GET | /api/streams |
Read |
| GET | /api/streams/{id} |
Read |
| POST | /api/streams |
Write |
| DELETE | /api/streams/{id} |
Write |
| POST | /api/streams/{id}/start |
Write |
| POST | /api/streams/{id}/pause |
Write |
| POST | /api/streams/{id}/stop |
Write |
| POST | /api/streams/{id}/settle |
Write |
| POST | /api/streams/{id}/withdraw |
Write |
| GET | /api/activity |
Read |
| GET | /api/identity/me |
Read |
| GET | /api/auth/wallet |
Challenge (20 req/min per IP) |
| POST | /api/auth/wallet |
Login (5 req/min per IP) |
The /api/auth/wallet endpoint uses IP-based rate limiting with stricter thresholds for login attempts:
| Operation | Limit | Window | Purpose |
|---|---|---|---|
| GET (challenge) | 20 requests | 1 minute | Prevent abuse of challenge generation |
| POST (login) | 5 requests | 1 minute | Prevent brute-force login attempts |
These limits apply per IP address and are independent of the general rate limiting system. Each IP is tracked separately, and limits are enforced using the same token bucket algorithm.
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please try again later."
}
}If your use case requires higher rate limits:
-
For production deployments: Contact StreamPay support with your:
- Expected request volume
- Use case description
- Whether you need per-key or per-wallet limits
-
For testing/development: The in-memory rate limit store is suitable for single-instance deployments.
Rate limiting emits structured logs for monitoring:
{
"event": "rate_limit_throttled",
"route": "/api/streams",
"limitType": "read",
"timestamp": "2026-04-28T12:00:00.000Z",
"identityType": "wallet",
"identityDisplay": "GATODH2T75IVFB..."
}Monitor these events to tune rate limits and detect potential abuse.
Rate limits use a token bucket algorithm, which allows for:
- Burst handling: Requests can use up to the limit in short bursts
- Smooth refill: Tokens refill at a constant rate
- Fairness: Each identifier gets an equal share of the limit
| Backend | Use Case | Configuration |
|---|---|---|
| In-Memory | Development, single-instance | Default (no config needed) |
| Redis | Production, multi-instance | Set RATE_LIMIT_STORE_TYPE=redis and RATE_LIMIT_REDIS_URL |
- Rate limit thresholds are not exposed in error responses (no information leakage)
- Internal metrics track throttle counts by route for alerting
- In-memory whitelist is for single-instance use only
- Handle 429 responses gracefully - Implement exponential backoff
- Use idempotency keys - For POST requests to safely retry on network failure
- Monitor your usage - Track response headers to stay within limits
- Batch requests when possible - Use list endpoints instead of individual GETs