PoofBit
Crash-risk scores for crypto: the Poof Index (11-111) for the top 250 coins and big exchanges, the market-wide Chaos Index, and the method behind them. Remote server, free API key.
Hosted MCP Server
npx add-mcp 'https://poofbit.com/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
GDPR Compliance
We use cookies to ensure you get the best experience on our website. By continuing to use our site, you accept our use of cookies (and chaos).
PoofBit API
Use the Poof Chaos Index and the Poof Index in your bots, dashboards and AI agents.
The Poof Chaos Index (PCI) is a market-wide, direction-neutral measure of turbulence from 0 to 100, computed from public market data. It is designed to be read next to Fear & Greed: sentiment tells you which way the crowd leans, PCI tells you how violently the market is moving.
The Poof Index assesses single coins from 11 to 111: the higher, the deeper the coin is in a poof state. Everything is available as JSON over HTTPS and as tools for AI agents over MCP.
Get an API key
Free and instant. Every request to /api/* and /mcp needs a key. Need higher limits? Create an account to get account tokens (120/min) and a watchlist.
Quick start
Plain JSON over HTTPS. Put your key in an environment variable and send it as a Bearer token:
export POOFBIT_KEY=pb_your_key_here
curl -H "Authorization: Bearer $POOFBIT_KEY" https://poofbit.com/api/pci
Authentication
Send your key with every request, in either header:
Authorization: Bearer YOUR_KEY(preferred)X-API-Key: YOUR_KEY
Keys are never accepted in the URL, because URLs end up in logs and browser history. We store only a hash of your key, so a lost key can't be recovered: create a new one.
A missing, unknown or revoked key returns 401 with a WWW-Authenticate: Bearer header:
{ "error": "Missing or invalid API key", "docs": "https://poofbit.com/docs#authentication" }
Going over the rate limit returns 429.
Free vs account
| Tier | Where to get it | Limits |
|---|---|---|
free | The form above, no account | 30 requests per minute and 1,000 per day |
account | Your account page, after confirming your email; up to 5 tokens | 120 requests per minute and 20,000 per day, plus the watchlist |
Account tokens look and work exactly like API keys (same headers). Limits count per key; days are UTC. Every keyed response tells you where you stand:
X-RateLimit-Limit: requests allowed per minute for this key.X-RateLimit-Remaining: requests left in the current minute.X-RateLimit-Tier:freeoraccount.
GET /api/pci
Returns the current Poof Chaos Index with its zone, the weighted components, the Fear & Greed reading, the combined quadrant, the daily history and the Global Poof Index.
| Field | Type | Description |
|---|---|---|
pci | integer | The index, 0 (calm) to 100 (maximum turbulence). |
zone | object | Zone the value falls into. |
zone.key | string | Stable machine-readable identifier. |
zone.name | string | Display name. |
zone.emoji | string | Display emoji. |
components | array | The weighted inputs behind the value. |
components[].key | string | Stable component identifier. |
components[].label | string | Display name. |
components[].weight | number | Share of the index, 0 to 1. Weights sum to 1. |
components[].risk | number | Component reading, 0 (calm) to 1 (extreme). Contributes 100 Γ weight Γ risk points. |
components[].detail | string | Human-readable description of the measured value. |
fear_greed | object | null | Crypto Fear & Greed reading; null when unavailable. |
fear_greed.value | integer | 0 (extreme fear) to 100 (extreme greed). |
fear_greed.classification | string | Text classification, e.g. "Greed". |
quadrant | object | null | PCI combined with Fear & Greed; null when fear_greed is null. |
quadrant.key | string | Stable identifier. |
quadrant.emoji | string | Display emoji. |
quadrant.name | string | Display name. |
quadrant.text | string | Short interpretation. |
history | array | One entry per recorded day, oldest first; the last entry is today's current value. |
history[].date | string | UTC date, YYYY-MM-DD. |
history[].pci | integer | Index value for that day. |
history[].source | string | live for values recorded on the day, reconstructed for earlier days rebuilt from historical market data. |
history_days | integer | Number of entries in history (up to one year plus today). |
stale | boolean | true when the data missed three refreshes in a row (market data normally refreshes every 20 minutes). |
updated_at | string | ISO 8601 UTC time the data was last refreshed. |
methodology | string | PCI formula version, currently "v2". History only contains values of this version. |
gpci | object | null | The Global Poof Index: how much of the market is in a poof state. null while it cannot be computed. |
gpci.value | integer | 11 (boringly solid) to 111 (total poof), on the Poof Index scale. |
gpci.zone | object | key, name, emoji of the Poof Index zone it falls into. |
gpci.share_in_poof | number | Share of coins in Red Flag Parade or worse, weighted by the square root of market cap (each coin capped at 15 %), 0 to 1. |
Example response:
{
"pci": 34,
"zone": { "key": "choppy", "name": "Choppy Waters", "emoji": "π" },
"components": [
{ "key": "volatility", "label": "Volatility", "weight": 0.3, "risk": 0.31, "detail": "Median daily swing β 3.6%" },
{ "key": "breadth", "label": "Breadth of big moves", "weight": 0.2, "risk": 0.26, "detail": "13 of 50 coins moved more than 5%" },
{ "key": "dispersion", "label": "Dispersion", "weight": 0.15, "risk": 0.4, "detail": "Spread of 24h moves 3.1%" },
{ "key": "swing", "label": "Market cap swing", "weight": 0.15, "risk": 0.22, "detail": "Top 48 market cap +1.1% in 24h" },
{ "key": "volume", "label": "Volume surge", "weight": 0.1, "risk": 0.45, "detail": "24h volume is 2.6% of the top 48 market cap" },
{ "key": "mania", "label": "Memecoin mania", "weight": 0.1, "risk": 0.52, "detail": "Trending coins average Poof Index 52" }
],
"fear_greed": { "value": 59, "classification": "Greed" },
"quadrant": { "key": "calm-greed", "emoji": "π", "name": "Calm Greed", "text": "Complacency mode. The quiet before the poof." },
"history": [
{ "date": "2026-10-07", "pci": 29, "source": "reconstructed" },
{ "date": "2026-10-08", "pci": 31, "source": "live" },
{ "date": "2026-10-09", "pci": 34, "source": "live" }
],
"history_days": 3,
"stale": false,
"updated_at": "2026-10-09T12:00:00+00:00",
"methodology": "v2",
"gpci": { "value": 24, "zone": { "key": "sus", "name": "Slightly Sus", "emoji": "π€¨" }, "share_in_poof": 0.08 }
}
GET /api/coins
Coins with their Poof Index, filtered, sorted and paged like the Poof Index table: the same parameters, the same result. Invalid parameter values fall back to the defaults (never an error). Repeat a parameter to pass several values.
| Parameter | Values | Description |
|---|---|---|
tab | top | all | trending | Top 50 by market cap (default), the top 250, or trending coins. |
q | text | Search in name and ticker. |
zone | solid | sus | flip | red | poof | Only these zones (repeatable). |
sort | poof | mcap | pc24h | pc7d | price | name | Default poof: highest Poof Index first. Coins without a value come last. |
dir | asc | desc | Default desc (asc for name). |
poof_min, poof_max | 11β111 | Poof Index range. |
cap | gt10b | 1b-10b | 100m-1b | lt100m | Market cap buckets (repeatable). |
ch24_min, ch24_max, ch7_min, ch7_max | number | 24h and 7d price change ranges, percent. |
futures | 1 | Only coins with a Binance perpetual. |
flag | hot | longs | shorts | leverage | Positioning flags, any of (repeatable). |
beta_min, beta_max | number | Market beta range. |
hide_stables | 1 | Leave out stablecoins, wrapped tokens and pegged assets. |
page | 1 and up | Page number; past the last page gives the last one. |
per_page | 25 | 50 | 100 | Page size, default 50. |
limit | 1β50 | Older way to set the page size, used when per_page is not given. Out-of-range values are clamped. |
| Field | Type | Description |
|---|---|---|
coins | array | Coin objects of this page, see below. |
tab, sort, dir | string | The values actually used. |
page, per_page | integer | The page returned and its size. |
total | integer | Coins left after the filters, over all pages. |
pages | integer | Number of pages (at least 1). |
filters | object | The filters actually used: q, zone, cap, futures, flag, hide_stables, and the *_min / *_max ranges (null when unset). |
stale | boolean | true when the list missed three refreshes in a row. |
updated_at | string | ISO 8601 UTC time the data was last refreshed. |
methodology | string | Poof Index version, currently "v3". |
coins[].id | string | CoinGecko id, use it with /api/coins/{id}. |
coins[].name, coins[].symbol | string | Display name and upper-case ticker. |
coins[].price | number | null | Price in USD. |
coins[].market_cap | number | null | Market cap in USD. |
coins[].rank | integer | null | Market cap rank. |
coins[].change_24h | number | null | Price change over 24h, percent. |
coins[].poof | integer | null | Poof Index, 11 (boringly solid) to 111 (total poof); null until the coin has 31 daily closes (sorted last). |
coins[].zone | object | null | key, name, emoji of the Poof Index zone; null with poof. |
coins[].components | array | One entry per signal: key, label, value (the measured signal) and contribution (how far it pushes the index, in log-odds; positive = up). Empty without a value. |
coins[].change_7d | number | null | Price change over 7d, percent. |
coins[].has_futures | boolean | The coin has a Binance perpetual. |
coins[].flags | array | Positioning flags (hot, longs, shorts, leverage). |
coins[].market_beta | number | null | Beta against the top-10 market. Context, not part of the index. |
curl -H "Authorization: Bearer $POOFBIT_KEY" "https://poofbit.com/api/coins?tab=all&zone=red&zone=poof&futures=1&sort=mcap&per_page=25"
Example response (one coin shown):
{
"coins": [
{
"id": "bitcoin", "name": "Bitcoin", "symbol": "BTC",
"price": 65000.0, "market_cap": 1300000000000, "rank": 1, "change_24h": 1.0,
"poof": 14, "change_7d": 2.1, "has_futures": true, "flags": [], "market_beta": 1.0,
"zone": { "key": "solid", "name": "Boringly Solid", "emoji": "π§±" },
"components": [
{ "key": "vol30", "label": "30-day volatility", "value": 0.021, "contribution": -0.32 },
{ "key": "dd90", "label": "Drop from 90-day high", "value": 0.08, "contribution": -0.72 }
]
}
],
"tab": "all", "sort": "mcap", "dir": "desc",
"page": 1, "per_page": 25, "total": 7, "pages": 1,
"filters": { "q": "", "zone": ["red", "poof"], "futures": true, "...": "..." },
"stale": false,
"updated_at": "2026-10-09T12:00:00+00:00",
"methodology": "v3"
}
GET /api/coins/{id}
One coin by CoinGecko id (lowercase letters, digits and dashes, e.g. bitcoin): the coin object from /api/coins plus its history.
| Field | Type | Description |
|---|---|---|
history | array | Daily Poof Index, up to 31 points: the last 30 days plus today, oldest first. Empty when the price history is unavailable; shorter for young coins. |
history[].date | string | UTC date, YYYY-MM-DD. |
history[].poof | integer | Poof Index for that day. |
past.yesterday, past.last_week, past.last_month | integer | null | Poof Index 1, 7 and 30 days ago; null when unknown. |
methodology | string | Poof Index version, currently "v3"; the whole history is computed with it. |
positioning | object | null | Context, not scored: the coin's Binance perpetual for the last closed UTC day (day); null without a perp or when older than 3 days. |
positioning.funding_rate, funding_7d | number | null | Funding as a fraction per 8 hours (the day's rates / 3) and its 7-day mean. |
positioning.open_interest_usd, oi_change_28d | number | null | Open interest at the day's close, and its change over 28 days (1.0 = +100 %). |
positioning.ls_accounts, ls_top_positions, taker_ratio | number | null | Long/short ratio of all accounts, of top traders' positions, and taker buy/sell volume. |
positioning.liq_long10, liq_short10 | number | null | Estimate: share of open interest a stated leverage model puts within 10 % below / above the price. |
positioning.flags | array | Up to three plain flags, e.g. "Funding hot", "Leverage piling up". |
market_beta | object | null | Context, not scored: {beta, correlation, days} of daily returns against the top-10 market over 60 days; null below 61 daily closes. |
markets | object | null | Context, not scored: where the coin trades. null when nothing from the last 14 days is known; each section is empty when its data is older. |
markets.native | boolean | The native coin of its own chain (no contract of its own). |
markets.contracts[] | array | {chain, chain_name, address, explorer_url}: the contract on each chain (CoinGecko platform id); explorer_url is null for chains we do not map. |
markets.cex[] | array | Up to 5 centralized exchanges by 24h volume, each with its biggest pair: {exchange, exchange_id, base, target, volume_usd, trade_url, trust_score}. |
markets.dex[] | array | Up to 3 DEX pools by liquidity across the coin's chains: {dex, network, chain, chain_name, pair, liquidity_usd, volume_24h_usd, pool_address, url} (GeckoTerminal). |
markets.updated_at | string | UTC day of the newest section. Links go to third-party sites and are not an endorsement. |
An invalid or unknown id returns 404 {"error": "Unknown coin"}.
curl -H "Authorization: Bearer $POOFBIT_KEY" https://poofbit.com/api/coins/bitcoin
Watchlist
The coins on your account's watchlist. Needs an account token; anonymous keys get 403:
{ "error": "Watchlist needs an account token" }
GET /api/watchlist
{"coins", "stale", "updated_at", "methodology"}, with the same coin objects as /api/coins.
PUT /api/watchlist/{id}
DELETE /api/watchlist/{id}
Add or remove one coin by CoinGecko id. Both answer {"ok": true} and are safe to repeat. Unknown id on PUT: 404 (DELETE answers ok for any id). Adding beyond 50 coins: 409.
curl -H "Authorization: Bearer $POOFBIT_TOKEN" https://poofbit.com/api/watchlist
curl -X PUT -H "Authorization: Bearer $POOFBIT_TOKEN" https://poofbit.com/api/watchlist/bitcoin
curl -X DELETE -H "Authorization: Bearer $POOFBIT_TOKEN" https://poofbit.com/api/watchlist/bitcoin
MCP for AI agents
PoofBit is a remote Model Context Protocol server, so Claude, Cursor and other agents can read the indexes as tools. Endpoint https://poofbit.com/mcp (Streamable HTTP), same API key and rate limit as the REST API. Use the https URL in production; some clients (mcp-remote) refuse plain http unless you pass --allow-http.
Claude Code
claude mcp add --transport http poofbit https://poofbit.com/mcp --header "Authorization: Bearer YOUR_KEY"
Cursor
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"poofbit": {
"url": "https://poofbit.com/mcp",
"headers": { "Authorization": "Bearer YOUR_KEY" }
}
}
}
Claude Desktop and other stdio-only clients
Bridge with mcp-remote (needs Node.js). Add to claude_desktop_config.json; the key goes in an environment variable so the header has no space in it:
{
"mcpServers": {
"poofbit": {
"command": "npx",
"args": ["mcp-remote", "https://poofbit.com/mcp", "--header", "Authorization:${AUTH_HEADER}"],
"env": { "AUTH_HEADER": "Bearer YOUR_KEY" }
}
}
}
The key goes in the Authorization: Bearer β¦ header, as in every snippet above. The URL is /mcp (a trailing slash also works). If your client says the server needs OAuth or authentication, the API key is missing, wrong or revoked: check the header.
Tools
| Tool | Input | Returns |
|---|---|---|
get_chaos_index | none | The current Poof Chaos Index and Global Poof Index, same as /api/pci. |
list_coins | tab, sort, limit | Coins with their Poof Index, same as /api/coins. limit defaults to 10 here. |
get_poof_index | coin_id | One coin with history and context (positioning, market beta, where it trades), same as /api/coins/{id}. |
explain_methodology | none | Formulas, weights, zones, quadrants, data sources and caveats. |
get_watchlist | none | Your watchlist, same as /api/watchlist. Account tokens only; anonymous keys get an error result. |
Try asking: βWhat's the Poof Chaos Index right now and which top-50 coins have the highest poof risk?β
Reading the index
Poof Chaos Index (market-wide, 0β100)
How turbulent the market has been over the last 24 hours and 7 days, 0β100, direction-neutral: a crash and a pump are equally chaotic: it describes now, not next week. Read it next to Fear & Greed as a second, independent axis. Computed over the top 50 coins by market cap, leaving out stablecoins and wrapped or staked tokens.
Zones
| PCI | Zone | Color |
|---|---|---|
| 0β20 | π΄ Zen Mode zen | #34a853 |
| 21β40 | π Choppy Waters choppy | #aef359 |
| 41β60 | π’ Rollercoaster coaster | #FFD200 |
| 61β80 | πͺοΈ High Chaos chaos | #fb6b1e |
| 81β100 | π₯ Total Meltdown meltdown | #ea4335 |
Quadrants
PCI is direction-neutral, so it is combined with Fear & Greed to tell calm from panic.
| Condition | Quadrant |
|---|---|
| Fear & Greed β₯ 50, PCI > 50 | π€ͺ Euphoric Chaos euphoric Everyone's a genius and nobody's selling. Classic top-risk territory. |
| Fear & Greed β₯ 50, PCI β€ 50 | π Calm Greed calm-greed Complacency mode. The quiet before the poof. |
| Fear & Greed < 50, PCI > 50 | π©Έ Capitulation Chaos capitulation Blood in the streets. Fortunes are made (and lost) here. |
| Fear & Greed < 50, PCI β€ 50 | π€« Quiet Fear quiet-fear Nobody cares. Historically, that's when patient people accumulate. |
Components
| Component | Weight | Measures |
|---|---|---|
| Volatility | 30% | Median day-to-day price swings of the top 50 coins over the last 7 days. |
| Breadth of big moves | 20% | Share of the top 50 that moved more than 5% in 24h, up or down. |
| Dispersion | 15% | How differently the top 50 moved in 24h. Coins pulling in opposite directions = chaos. |
| Market cap swing | 15% | How much the combined market cap of the top 50 moved in 24h. |
| Volume surge | 10% | The top 50's 24h trading volume compared to their market cap. |
| Memecoin mania | 10% | Average Poof Index of trending coins. Hot garbage trending = mania. |
Global Poof Index (market-wide, 11β111)
How much of the market is in a poof state right now. It has no model of its own: it averages the Poof Index of the first 100 coins of the PCI universe that have one, weighted by the square root of market cap (no coin above 15%), with a power mean that lets a few coins deep in a poof pull it up. Shown on the Poof Index scale and zones. Next to it: the share of the market in Red Flag Parade or worse. It describes the present state only and gives no early warning: PCI stays the turbulence gauge (see Does it work?).
Poof Index (one coin, 11β111)
An assessment of a coin's current poof state, learned from 9 years of Binance daily prices, delisted coins included. Six signals from the coin's daily closes go through a logistic model: L (0β100) is its probability that a coin in this state is in a poof (checked against what happened to past coins in similar states). The index is 11 + L, rounded; 11 is the floor, because crypto is never 0% poof.
| Signal | Measures | Higher signal |
|---|---|---|
| 30-day volatility | How violently the price moved day to day over the last 30 days. | raises the index |
| Drop from 90-day high | How far the price is below its highest close of the last 90 days. | raises the index |
| Drop from 1-year high | How far the price is below its highest close of the last year. | raises the index |
| 7-day move | How far the price moved over the last 7 days. | lowers the index |
| 30-day move | How far the price moved over the last 30 days. | lowers the index |
| Coin age | How long the coin has had a price. Young coins go poof more often. | lowers the index |
Overheating
A coin at a fresh high has no drawdown, so the six signals read it as calm, even right after a vertical run. A second reading covers that: how much further the coin ran from its 14- and 30-day lows than the typical top coin did that day. From past coins in the same spot we take the chance that the price halves within 90 days, and keep only the part above a coin that simply moved with the market. The index shows the higher of the two readings. A coin 3Γ ahead of the market in two weeks reads about 49, 5Γ or more about 65. When the whole market runs, nobody is ahead of it and the reading stays at zero.
What comes next
The six signals say how deep a coin is in a poof now. One more signal looks the other way: of past coins that stood where this coin stands, how many lost half their price within 90 days. The index is never below that share (since v3.3). It compares the coin with the other top coins that day (how volatile it is, how old, how far below its highs, how it moved this month, how closely it follows Bitcoin) and adds how far it ran ahead of the market. Volatile young coins read high, old steady ones low. Because every reading is a place among the day's coins, a market-wide move by itself changes nobody's place. The share is an average over 2021β2026 and runs from 4% to 57%.
A coin needs 31 daily closes for a value; until then lists show βββ. βWhy N?β on a coin page shows how far each signal pushes the index up or down compared with a typical coin. Coin age counts from the coin's listing on Binance, as in the research; for coins Binance doesn't list, from the earlier of its all-time high and low dates. A coin with neither counts as old once we have known its price for a year.
| Poof Index | Zone | Color |
|---|---|---|
| 11β20 | π§± Boringly Solid solid | #34a853 |
| 21β35 | π€¨ Slightly Sus sus | #aef359 |
| 36β55 | π² Coin Flip flip | #FFD200 |
| 56β75 | π© Red Flag Parade red | #fb6b1e |
| 76β111 | π¨ Total Poof poof | #ea4335 |
Context (shown, not scored)
- Size β Smaller market cap = easier to push around.
- Dilution β Fully diluted value vs market cap: how many tokens are still waiting to be dumped on you.
- Crash from ATH β How far the price has fallen from its all-time high.
- Volume anomaly β Trading volume vs market cap. Too much smells like wash trading.
Positioning (context, not scored)
Coins with a Binance perpetual show funding, open interest, long/short and taker ratios, and an estimated liquidation pressure: a model that spreads each day's new open interest over 10x / 25x / 50x leverage (50 / 30 / 20 %) at that day's price. Flags: Funding hot (7-day mean β₯ 0.05 % per 8 h), Shorts paying (β€ β0.03 %), Leverage piling up (open interest +100 % in 28 days), Crowded longs / Crowded shorts (long/short accounts β₯ 3 / β€ 0.5), Long liquidations stacked below (half the open interest within 10 % below). The market beta is the 60-day beta against the top-10 coins. None of this feeds the Poof Index: tested, it did not make the index better.
Every payload carries methodology ("v3.3" for the Poof Index, "v2" for PCI) so you can tell formula versions apart. The Poof Index describes now, not next week.
Live track record
What we showed on a day against what the price did next, counted from the values published on that day (2026-10-10 to 2026-10-12), never recomputed. "Fell" means the price went 30% or more below that day's close within the next 30 days. It updates daily.
| Poof Index zone that day | Coin-days | Fell 30%+ within 30 days |
|---|---|---|
| π§± Boringly Solid | 673 | 24% |
| π€¨ Slightly Sus | 58 | 24% |
| π² Coin Flip | 11 | 36% |
| π© Red Flag Parade | 8 | 88% |
| π¨ Total Poof | 5 | 100% |
Does it work?
Poof Index
Tested walk-forward, year by year from 2021 to 2025: each year was scored by a model trained only on the years before it.
- What it does: it tells coins in a poof state from the rest with an AUC of 0.695. It flagged 9% of 1,221 collapses before they were obvious (before the drawdown passed 50%), a median 36 days earlier, with 1.5% false alarms. It never flagged BTC, ETH or SOL. Lead times are from the backtest, not a promise.
- Overheating: tested the same way through 2026. After an overheat reading of 36 or more, the price halved within 90 days 53% of the time (39β77% depending on the year), against 21% for all coins. So about half of these coins did not halve. On the day a collapse peaked, the index stood at 36 or more for 14% of collapses (3% before). BTC and ETH never got a reading above 23. It only sees run-ups: a slow death from a quiet top still shows up late.
- What comes next: tested the same way through 2026, coin against coin within each day. The tenth of coins this signal rated lowest halved within 90 days 10% of the time, the tenth it rated highest 33%, in that order in every year. It ranks what comes next better than the Poof Index does (AUC 0.70 against 0.65 for the index without it), which is why it is part of the index since v3.3. Before, Boringly Solid and Slightly Sus coins halved about equally often (19% and 21%); now the zones read 7%, 19%, 27%, 31% and 27% from Solid to Total Poof. Total Poof coins have mostly fallen already, so fewer of them halve again. The order holds from year to year; the level does not: in 2023 4% of all coins halved, in 2021 31%. It saw nothing unusual in LUNA or FTT before they broke.
- A heavier model: a heavier research model tested alongside (not shipped) flagged 17%, 26 days earlier, at 1.75% false alarms.
- What it can't: LUNA and FTX gave no warning: what broke them was outside price data. Hacks, frauds, unlocks and exchange trouble show up only once the price moves.
- Levels drift: the share of coins in a poof state ran from 2% to 38% a year, so the same number overstates the risk in a calm year and understates it in a crash.
Global Poof Index
It describes the present state only. Its correlation with the share of the market in a poof state at the time is 0.40 [0.11, 0.59], against 0.15 for PCI (55 monthly points). Against what happened over the following 90 days it did worse than PCI (0.12 vs 0.43): PCI stays the turbulence gauge and G-PCI is not an early-warning signal.
Poof Chaos Index
We backtested PCI on a year of daily CoinGecko data for 150 coins, fitted every constant on the first 8 months and tested once on the last 4 (JuneβOctober 2026). 95% confidence intervals in brackets.
| Index | Score | Test |
|---|---|---|
| PCI v2 | 0.845 | [0.634, 0.884] correlation with the same 7 days of turbulence (previous formula 0.796) |
| PCI v2, next week | 0.42 | correlation with the next 7 days: no better than assuming last week continues (0.44) |
- Survivorship: the backtest only had coins that are still around.
- Calm test quarter: expect lower accuracy in a stressed market; one year of data is one market regime.
- Memecoin mania has no history to calibrate on yet; its scale will be re-anchored on live data.
Code examples
curl
curl -s -H "Authorization: Bearer $POOFBIT_KEY" https://poofbit.com/api/pci
Python
import os
import requests
key = os.environ["POOFBIT_KEY"]
headers = {"Authorization": f"Bearer {key}"}
data = requests.get("https://poofbit.com/api/pci", headers=headers, timeout=10).json()
print(data["pci"], data["zone"]["name"])
JavaScript
const res = await fetch("https://poofbit.com/api/pci", {
headers: { Authorization: \`Bearer ${process.env.POOFBIT_KEY}\` },
});
const data = await res.json();
console.log(data.pci, data.zone.name);
Errors & caching
- 401: missing, unknown or revoked key. See Authentication.
- 403: the watchlist needs an account token.
- 404: unknown coin id (
/api/coins/{id}and watchlist). - 409: the watchlist is full (50 coins).
- 429: rate limit exceeded. Wait
Retry-Afterseconds. - 503 with
{"error": "..."}: the data is temporarily unavailable. Retry in a minute. - Successful responses carry
Cache-Control: private, max-age=60, except/api/watchlist, which isprivate, no-cache. Market data refreshes every 20 minutes. - Request bodies are limited to 64 KB.
stale: truemeans the data missed three refreshes in a row;updated_atsays when it was last refreshed.
Rate limits
- Free keys: 30 requests per minute and 1,000 per day. Account tokens: 120 per minute and 20,000 per day. REST and MCP count together; days are UTC.
- Over the per-minute limit you get 429
{"error": "Rate limit exceeded", "retry_after": 12}and aRetry-Afterheader. - Over the daily limit you get 429
{"error": "Daily limit exceeded", "retry_after": 3600}, withRetry-Aftercounting down to 00:00 UTC. - Data freshness is 20 minutes, so polling more than once a minute returns nothing new.
- Up to 3 new keys per network per hour.
Exchange Poof Index
A rating from 11 to 111 for centralized exchanges, built from the reserves they publish on-chain. Like the coin index, higher is worse. It reads what the wallets hold, not what the exchange says.
| Signal | What it measures |
|---|---|
| Net flow, 7 days | How much of the exchange's reserves left or arrived over the last 7 days. Outflows add points, inflows take a few away. |
| Net flow, 30 days | The same over 30 days, to tell a one-off move from a steady drain. |
| Own-token share | The share of reserves held in the exchange's own token. Counted in USD; its value depends on the exchange itself. |
| Reserve quality | The average Poof Index of the other coins it holds, weighted by dollar value. Riskier coins add points. |
| Stablecoin health | The share of reserves in stablecoins trading away from their peg. |
| Size | Total reserves. Smaller reserves add points; larger ones take a few away. |
| Hacks | Past hacks, counted more when recent and half as much when the funds were returned. |
Flows are counted in coins, not price: a token's move in value caused only by its price does not count as money leaving, and only tokens present on both days are compared. The exchange's own token is counted in USD only.
Flows are priced at the lower of a token's two prices, so a token whose amount was re-based does not read as money leaving.
A sudden jump in the 7-day outflow is scored at the day before's milder reading until it holds a second day: one-day jumps are as often an exchange moving its own wallets as a run. On past data this removed 37% of red episodes and left the readings after known hacks and runs the same or a day later.
Does it work?
- What it shows: how fast coins are leaving the wallets an exchange has published, and how fragile those visible reserves look. After the Bybit hack of February 2025 it went from 18 to 62 in two days.
- What it can't: it reacts, it does not warn. A week before seven known stress events the exchange in question sat among the calmest. A low number means no visible run today, not a safe exchange. It is not a probability of failure.
- What nobody outside can see: what an exchange owes its customers, its off-chain and bank holdings, wallets it has not published, loans to related companies. FTX failed on exactly those.
- Not tested on real failures: public reserve history starts in November 2022 and holds none of the exchanges that failed, so the weights are hand-picked, not fitted. On the 63 exchanges we could test, most of what the index ranks is size: small exchanges lose their visible reserves more often.
- A high number is not always a run: an exchange moving coins between its own wallets, or changing its published wallet list, looks the same from outside.
Reserves unknown means we cannot rate the exchange: it has not published its wallets, we have less than 30 days of history for it, or its data is not fresh.