Rate Limits & Errors
Rate Limits & Errors
Section titled “Rate Limits & Errors”Rate Limits
Section titled “Rate Limits”Cerebrus Pulse enforces rate limits across multiple dimensions to ensure fair access.
| Dimension | Limit | Window |
|---|---|---|
| Per IP | 12 requests | 1 minute |
| Per wallet | 20 paid requests | 1 minute |
| Concurrent | 3 requests | Simultaneous |
| Daily | 2,000 requests per IP | 24 hours |
How Limits Are Tracked
Section titled “How Limits Are Tracked”- IP-based: Tracked by your client’s source IP address
- Wallet-based: Tracked by the payer of the payment the gateway verified (the EIP-3009
fromaddress on Base). A client-supplied header does not count - Concurrent: Maximum simultaneous requests being processed, across all callers
- Daily: Per IP, reset every 24 hours, with a far higher global backstop
Rate Limit Response
Section titled “Rate Limit Response”When a limit is exceeded, you receive:
HTTP/1.1 429 Too Many RequestsContent-Type: application/json
{ "detail": "Rate limit exceeded (per-IP)", "limit": 12, "window": 60}Free Endpoints
Section titled “Free Endpoints”GET /health and GET /coins are not rate limited. The free GET /demo/{coin} (BTC and ETH only) allows 3 requests per minute per IP.
Error Codes
Section titled “Error Codes”| Status | Meaning | When It Happens |
|---|---|---|
| 400 | Bad Request | An invalid timeframe or integer parameter, refused before any price is quoted; or the engine could not answer (for example no data for the market), which is not charged |
| 402 | Payment Required | The standard x402 flow: pay with an x402 v2 client. A 402 after paying means the payment was not accepted, and nothing was settled |
| 404 | Not Found | An unknown coin, refused before any price is quoted |
| 429 | Too Many Requests | A rate limit above was exceeded |
| 500 | Internal Server Error | An unexpected engine failure (not charged) |
| 503 | Service Unavailable | The service is switched off (retry_after: 3600), payments are down, or an upstream data feed is missing or stale (Retry-After: 300). No price is quoted |
| 504 | Gateway Timeout | The engine took longer than 15 seconds (not charged). Try again |
A payment settles only after the gateway has an answer: any 4xx or 5xx after you paid is not charged.
Error Response Format
Section titled “Error Response Format”Errors are JSON with a detail string. A refused parameter is also named in param, often with what is
allowed:
{"detail": "Unsupported timeframes: 2h. Allowed: 5m, 15m, 1h, 4h, 1d, 1w.", "param": "timeframes", "allowed": ["5m", "15m", "1h", "4h", "1d", "1w"]}{"detail": "Unknown coin 'NOTACOIN'. GET /coins lists the supported symbols.", "param": "coin", "did_you_mean": ["NEAR"], "supported_coins": "/coins"}503 Example
Section titled “503 Example”{"detail": "Service temporarily disabled", "retry_after": 3600}Best Practices
Section titled “Best Practices”- Check
/healthfirst — Before batch operations, verify the gateway is operational and the kill switch is enabled. - Use backoff on 429 — Wait the indicated window duration before retrying.
- Don’t retry on 400 — These are client errors. Fix the request before retrying.
- Retry on 504 — Engine timeouts are usually transient. A single retry typically succeeds.
- Respect 503 — Wait for the
Retry-Afterperiod before retrying. - Use
/bundlefor multi-data — Instead of calling/pulse+/sentiment+/fundingseparately (3 requests), use/bundle(1 request), which uses one rate-limit slot instead of three. Its page shows how its price compares with the three calls.