Usage limits
Limits depend on your plan and are counted per account, all keys together. They are announced in advance, every refusal states its reason, and nothing is ever truncated in silence. The values on this page are those of the plans catalogue.
#The limits by plan
Four plans, four sets of limits. The Enterprise plan is negotiated; it has no default value.
| Limit | Free | Traders | Financial | Startup |
|---|---|---|---|---|
| Requests per month | 10,000 | 200,000 | 2,000,000 | 20,000,000 |
| Rate limit, per minute | 30 | 60 | 300 | 600 |
| Burst tolerated | 10 | 20 | 50 | 100 |
| Data families | 4 / 12 | 7 / 12 | 12 / 12 | 12 / 12 |
| REST endpoints open | 41 | 77 | 119 | 119 |
| Simultaneous WebSocket connections | — | 3 | 10 | 20 |
The catalogue documents 121 paths, two of which are out-of-quota probes (/v1/health and /v1/status) counted for nobody. Only the first answers without a key.
#Rate limit and monthly quota
Two counters, both per account: not per address, not per key. Rotating a key, or spreading the traffic over several addresses, changes neither one nor the other.
- The rate limit is measured per minute, with a tolerated burst: a few requests at once go through, beyond that the following ones are smoothed then refused. The refusal is a
429withRetry-After: 1. - The monthly quota counts every request subject to quota, over the calendar month in UTC, and restarts from zero on the first day of the month. Once exhausted, it returns a
429withRetry-After: 3600until it renews, or until a plan change, which is immediate.
HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-Deny-Reason: rate
{"status":"error","timestamp":1775648290510,"detail":"Debit depasse : votre offre autorise un nombre limite de requetes par minute.","retry_after":1}The X-Deny-Reason header carries the reason for any refusal tied to the plan (rate, quota, family, websocket or key), and the body repeats it in plain words in detail. There is no counter header on normal responses: the state of the quota is read in the console, which warns at 80 % then at the first refused request.
#The data families
Every endpoint belongs to exactly one quota family, and every plan opens a set of families. A family missing from your plan is missing on every channel: the REST route returns a 403, the snapshot removes its fields and lists them in out_of_plan_fields, the WebSocket stream refuses the channel.
| Family | Free | Traders | Financial | Startup |
|---|---|---|---|---|
| Price and volume prix-volume | yes | yes | yes | yes |
| Derivatives derives | yes | yes | yes | yes |
| Microstructure microstructure | — | yes | yes | yes |
| Raw ticks ticks | — | — | yes | yes |
| Options options | — | yes | yes | yes |
| Snapshot snapshot | — | yes | yes | yes |
| Indicators indicateurs | yes | yes | yes | yes |
| Macro macro | yes | yes | yes | yes |
| On-chain onchain | — | — | yes | yes |
| Sentiment sentiment | — | — | yes | yes |
| ETF etf | — | — | yes | yes |
| Tokenomics tokenomics | — | — | yes | yes |
HTTP/1.1 403 Forbidden
X-Deny-Reason: family
{"status":"error","timestamp":1775648290510,"detail":"Cette famille de donnees n est pas incluse dans votre offre."}The mapping between the thirteen families of the catalogue and these twelve quota families is given on the plans page; the one between a path and its family is in the endpoint catalogue.
#How far back the history goes
History depth depends on the plan and on the timeframe. It is a rolling window from now, not a per-request ceiling: yesterday is outside the plan in 1 min candles on Free, whatever the pagination.
| Timeframe | Free | Traders | Financial | Startup |
|---|---|---|---|---|
1m | 1 h | 24 h | 3 days | 1 week |
5m | 4 h | 3 days | 1 week | 30 days |
15m | 4 h | 3 days | 1 week | 30 days |
1h | 24 h | 1 week | 30 days | 90 days |
4h | 1 week | 30 days | 72 days | Full |
1d | 30 days | Full | Full | Full |
ticks | — | — | 1 h | 24 h |
30mfollows the window of1h,1wthat of1d: “Full” therefore also holds for the week wherever it holds for the day.- Routes without a timeframe (
since_ms/until_mshistories, daily series, funding) are bounded by the1hwindow of the plan: 24 h on Free, 1 week on Traders, 30 days on Financial, 90 days on Startup. - Tick-by-tick routes (
/v1/raw/spot-ticks,/v1/raw/futures-ticks,/v1/raw/trades) have their own window, theticksrow above, and are only open where the family is: 1 h on Financial, 24 h on Startup. - The check bears on the oldest bound actually reached:
limitmultiplied by the duration of the timeframe, orsince_ms, or anuntil_msalready beyond the window.
Going over returns an explicit 403, never a truncated response: the detail says what was asked for, what the plan allows and the maximum usable limit.
HTTP/1.1 403 Forbidden
{"detail":"Profondeur d'historique hors offre : 30 jour(s) demandes en 1m, votre offre en autorise 1 heure(s) (soit limit=60 au maximum sur ce timeframe, et aucune borne since_ms/until_ms au-dela de cette fenetre)."}What the data itself contains
Beyond the window of the plan, the depth available depends on the family: Fear & Greed since 2018, on-chain valuation and macro over several years, inter-venue spreads over two days only. The /v1/macro/intraday/series catalogue gives the exact value for each macro instrument.
#Stream connections
The WebSocket stream is open from Traders upwards. The key is checked at the handshake: a plan without the stream receives a 403 and the connection is not established. The ceiling on simultaneous connections holds for the whole account, all keys together; the connection too many is closed with code 4003 and the ceiling in the reason.
| Limit | When exceeded |
|---|---|
| Simultaneous connections per account: 3 on Traders, 10 on Financial, 20 on Startup | close 4003, the ceiling in the reason |
| Stream missing from the plan (Free) | 403 at the handshake, X-Deny-Reason: websocket |
| Channel of a family outside the plan | op: error, the subscription is not applied |
| Openings: 1 per second, burst of 10 | 429 at the handshake |
| Send queue of 256 frames | the oldest ones dropped, seq jumps |
| 10 overflows tolerated | close 4003, reason “client too slow” |
A connection that stays subscribed costs far less than repeated polling: if you call the same endpoint every second, the stream is the right answer. See WebSocket stream.
#Depth ceilings
Independently of the plan, every route bounds its limit. These ceilings are technical; the window of the plan applies on top, and it is the stricter of the two that counts.
| Surface | Type | Description |
|---|---|---|
REST endpoints | limit | Most often 1000; 500 on the long/short ratio and the inter-venue spreads; 10 000 on individual ticks. The exact ceiling appears in the parameter table of each route. |
Snapshot | one ceiling per field | 1000 candles, 1440 minutes for the per-minute series, 3600 seconds for aggregated trades, 10 000 for ticks; 200 windows for the CVD, 50 for the inter-venue spreads. Going over returns a 400 or a 422; going beyond the window of the plan returns a 403. |
Indicators | results + warm-up ≤ 1000 | Fifty instances per call at most. The refusal indicates the maximum period usable for the number of results asked for. |
#What to do
Respect the announced delay, and do not replay a 403
On a 429 as on a 503, the Retry-After header gives the delay. A 403 tied to the plan (family, depth, stream) will not change by being replayed: read X-Deny-Reason and detail, then correct the request or change plan.
import time
import httpx
def get(client: httpx.Client, path: str, **params):
"""Retry on the delay the server announces, never on a 403."""
for attempt in range(4):
response = client.get(path, params=params)
if response.status_code in (429, 503):
# The server knows when it will be ready: do not invent a delay.
# On an exhausted monthly quota (X-Deny-Reason: quota), Retry-After
# is an hour: no point insisting, the counter restarts on the 1st.
wait = float(response.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
continue
# 403: the request is outside the plan (family, depth, key). Replaying
# it as is will produce exactly the same response.
response.raise_for_status()
return response.json()
raise RuntimeError("the service is still unavailable after 4 attempts")Group rather than repeat
The snapshot brings back up to sixty-one fields in one request, counted once. For a dashboard, that is one call per cycle instead of ten, and ten times less quota.
# Three calls where one is enough.
GET /v1/funding/rate?symbol=BTCUSDT
GET /v1/basis?symbol=BTCUSDT
GET /v1/oi/delta?symbol=BTCUSDT
# The same result, in one request (from Traders upwards).
GET /v1/snapshot?symbol=BTCUSDT&funding_rate_8h=true&basis=1&oi_delta=1Do not ask again for what does not move
Fear & Greed publishes one point a day. ETF fundamentals are quarterly. Daily macro series move once a day. Querying them by the minute consumes quota without learning anything: pace each family on the rhythm of its data.