{"schemaVersion":1,"name":"PerpFinder Public Data API","description":"Stable, keyless and CORS-open crypto derivatives datasets intended for humans, search systems and software agents.","lastReviewed":"2026-09-21","documentation":"https://perpfinder.com/docs/api","openapi":"https://perpfinder.com/openapi.json","llms":"https://perpfinder.com/llms.txt","llmsFull":"https://perpfinder.com/llms-full.txt","dataDefinitions":"https://perpfinder.com/data-definitions","status":"https://perpfinder.com/status","mcp":{"endpoint":"https://perpfinder.com/api/mcp","documentation":"https://perpfinder.com/docs/mcp","transport":"streamable-http (stateless, POST only)","protocolVersions":["2025-11-25","2025-06-18","2025-03-26"],"tools":["get_cheapest_venue","get_venue_fees","get_funding","get_volume_ranking","get_venue_access"],"readOnly":true},"rateLimitsPerMinute":{"/api/data/perps":60,"/api/data/slippage":30,"/api/data/slippage-spot":30,"/api/data/dex-enrichment":60,"/api/data/perps-chart":60,"/api/data/volume":40,"/api/data/open-interest":40,"/api/data/oi-long-short":60,"/api/data/funding-rates":40,"/api/data/fees":60,"/api/data/liquidations":60,"/api/data/liquidations-history":40,"/api/data/options":40,"/api/data/options-history":40,"/api/data/volume-quality":40,"/api/data/rwa-markets":60,"/api/data/mica":30,"/api/data/premium":60,"/api/data/fear-greed":60,"/api/data/funding-history":40,"/api/data/funding-prediction-accuracy":30,"/api/data/volume-quality-history":40,"/api/data/volume-ranking":40,"/api/data/venue-history":40,"/api/data/cost-history":40,"/api/data/builder-fees":40,"/api/mcp":60},"attribution":"Data: PerpFinder (https://perpfinder.com)","conventions":{"missingValues":"null, never zero-filled","totalExecutionCost":"feeBps + halfSpreadBps + slippageBps","statusFields":["dataStatus","coverage","generatedAt","upstreamTimestamp","schemaVersion","sources"]},"endpoints":[{"path":"/api/data/perps","params":"","description":"Perp DEX volume overview (24h/7d/30d, change %, per protocol).","fields":"protocols[], dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/slippage","params":"?asset=BTC&size=100000&feeType=taker|maker&side=buy|sell","description":"Live perp execution-cost ladder from order books and supported oracle/pool models. Total cost is fee + half-spread + size-dependent impact beyond the best quote. A venue that cannot fill the order publishes totalBps null and keeps its partial-fill numbers under partial. depthConfidence low marks displayed depth the plausibility gate could not confirm; such rows rank after confirmed rows. An oracle venue has no book: GMX publishes the size-dependent GMX v2 position impact read from the on-chain DataStore through the GMX Reader, in priceImpactBps, with slippageModel onchain-position-impact-v2 and slippageConfidence medium; slippageSourceUrl names the contract that was read. Caching: a healthy answer carries Cache-Control public, max-age=10, s-maxage=25, must-revalidate, so one measurement serves every reader for the engine TTL; partial and stale answers use max-age=0, s-maxage=5, must-revalidate so readers see a completed background refresh before its fresh window expires. X-Cache states where the answer came from: HIT (this instance), SHARED (the shared result store, inside the TTL), STALE-SHARED or STALE (a labelled older result, with staleAgeSeconds, refreshed behind the response), MISS (measured now) or UNAVAILABLE (nothing inside the stale cap).","fields":"asset, sizeUsd, side, results[].{exchange,feeBps,feeBpsMin,feeBpsMax,feeModel,slippageBps,halfSpreadBps,spreadBps,totalBps,midPrice,vwap,sufficient,fillStatus,depthFetchedUsd,depthConfidence,depthConfidenceReason,rankingEligible,partial,quoteStatus,maxExecutableSizeUsd}, coverage, referenceMidSource, meta, dataStatus, generatedAt, schemaVersion, sources, ETag","public":true},{"path":"/api/data/slippage-spot","params":"?asset=BTC&size=10000&feeType=taker|maker&side=buy|sell","description":"Live spot execution-cost ladder using venue order books, pair-specific fees, spread, VWAP impact and explicit depth coverage.","fields":"asset, sizeUsd, side, results[].{exchange,baseAsset,quoteAsset,feeBps,slippageBps,halfSpreadBps,spreadBps,totalBps,midPrice,vwap,sufficient,fillStatus,depthFetchedUsd,depthConfidence,depthConfidenceReason,partial}, coverage, meta, dataStatus, generatedAt, schemaVersion, sources, ETag","public":true},{"path":"/api/data/dex-enrichment","params":"","description":"Direct DEX market enrichment: OI, volume, funding, prices, protocol stats and venue coverage. fetchedAt is the time the upstreams were read — cross-venue funding predictions are judged against it, not the serve clock.","fields":"protocols[], crossVenueFunding, fetchedAt, coverage.{requested,succeeded,failed,rejected,retired}, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/perps-chart","params":"?days=90","description":"Aggregate daily perp-volume time series (DefiLlama) plus total open interest per day from our own snapshots. oi is absent on days with no capture — never zero-filled.","fields":"chart[{date,volume,oi?}], oiCoverage.{daysWithOi,days,note}, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/volume","params":"","description":"24h volume per venue from direct venue-reported perp tickers (CEX) and perp-DEX protocol APIs, with top symbols. Each row carries venueType so consumers can split CEX from DEX. exchanges[] is sorted by volume24h and holds the CEX rows plus Hyperliquid and dYdX (both venueType dex); every other perp DEX sits in dexVenues[], and dexTotalVolume is the sum of dexVenues[] only. Two hold-out rules keep a row visible while keeping its figure out of totalVolume. spikeFlagged[] names venues whose reported 24h volume is above 3x their own 7-day median (row carries volumeSpike true; the hold-out ends when the print holds). unverified[] names venues whose reported turnover PerpFinder cannot verify against an open-interest feed or an order book of matching size (row carries volumeUnverified true; the hold-out is permanent until an editorial review removes the entry). heldOut[] is the union, one {name, reason} per excluded venue, and each row carries heldOut set to the string unverified, the string spike, or null. change_1d is the day-over-day change of our captured snapshot total between the two newest calendar-adjacent captures, with every heldOut venue removed from both days, so it sits on the same basis as totalVolume; null when the two captures are not one day apart.","fields":"exchanges[].{name,volume24h,symbolCount,topSymbols[],venueType,volumeSpike?,volumeUnverified?,heldOut}, totalVolume, spikeFlagged[], unverified[], heldOut[].{name,reason}, dexVenues[], dexTotalVolume, noFeed[], change_1d, failed[], venueSlugs, updatedAt, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/open-interest","params":"","description":"Open interest per venue and the aggregate total. byExchange[] keeps the historical CEX list (plus Hyperliquid and dYdX); other perp DEXes are additive under dexVenues[]. Three totals, all in USD: totalOI is the sum of byExchange[] only (unchanged for existing consumers), cexTotalOI is the sum of the byExchange[] rows tagged venueType cex, and totalOIAllVenues is totalOI + dexTotalOI. coverage.cex and coverage.dex count the venues in THIS response; the /open-interest page replaces its initial server snapshot with this feed on each successful refresh.","fields":"totalOI, cexTotalOI, totalOIAllVenues, byExchange[].{name,oi,venueType}, dexVenues[], dexTotalOI, failed[], venueSlugs, coverage.{cex,dex,failed,noFeed,rejected,symbolCoverage}, updatedAt, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/oi-long-short","params":"","description":"DEX long vs short open-interest split per protocol.","fields":"protocols[], totalLong, totalShort, updatedAt, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/funding-rates","params":"?asset=BTC,ETH&venue=Binance,Bybit&limit=50","description":"Live funding-rate matrix: asset × exchange (normalized 1h). Missing OI/price are null with per-venue field support and explicit feed coverage. Venues that report a per-market interval (Binance, Bybit, OKX, Bitget, MEXC, Gate.io, BingX, KuCoin, Phemex, HTX, BloFin, Orderly, Aster) keep the raw rate and that interval; a market with no reported interval gets no rate. When only the interval request fails, the last reported interval of the market (at most 24 h old) is used and marked intervalSource \"last-known\" with intervalAgeMs. Optional asset/venue/limit filters narrow the matrix; a venue filter recomputes the per-row aggregates.","fields":"rows[].exchanges.{rate1h,rawRate?,intervalHours?,intervalSource?,intervalAgeMs?,oi,price}, exchanges[], coverage, updatedAt, meta.fieldSupport, meta.venueSlugs, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/fees","params":"","description":"Protocol fees (DEX, 24h/7d/30d per protocol) — aggregator-reported protocol fees, one row per Derivatives protocol. Fees paid and protocol-retained revenue are different measures. It carries no CEX rows: a CEX figure on /fees/generated is that venue’s 24h volume from /api/data/volume multiplied by a maker/taker rate. The volume rule therefore decides the CEX estimate too — a venue that /api/data/volume holds out, either as volumeSpike (24h volume above 3x its own 7-day median) or as volumeUnverified (reported turnover we cannot verify), keeps its row and its chip on /fees/generated, and stays out of the 24h fee total and the share bars, exactly as it stays out of totalVolume.","fields":"protocols[], dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/liquidations","params":"","description":"Liquidations 24h/4h/1h, long vs short split. Binance and Bybit come from our own capture of their forced-close WebSockets; OKX, Gate.io, HTX and GMX come from their public REST feeds. meta.coverage states how much of the last 24 hours the capture actually covered and which venues have no continuous capture. Captured-venue windows are summed from stored five-minute slots, so a window edge includes the slot it falls inside.","fields":"events[], summary, meta.{venues,missingVenues,windowHours,coverage.{status,collector24h,collectorPerVenue,venuesWithoutCollector,collectorSince}}, updatedAt, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources","public":true},{"path":"/api/data/liquidations-history","params":"?hours=24|168&format=json|csv","description":"Hourly liquidation history for Binance and Bybit from our own socket capture. Ledger v2 uses Bybit position sides and observed heartbeat windows; v1 remains separate. An hour with no capture returns null totals, never 0, and every bucket carries its coverage share.","fields":"collectorVersion, methodologyNote, series[].{t,longUsd,shortUsd,events,coverage,byVenue}, coverage.{fraction,perVenue,hoursWithCoverage,hoursRequested}, collectorSince, observedTotalUsd, hours, venues[], updatedAt, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources","public":true},{"path":"/api/data/options","params":"","description":"BTC/ETH options market state: mark IV per strike/expiry, ATM term structure, put/call, Deribit DVOL (attributed), expiries.","fields":"status, updatedAt, assets.{BTC,ETH}.{asset,venue,status,updatedAt,spotIndex,dvol,summary,termStructure[],skew[],skewExpiry,expiries[]}, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/options-history","params":"?asset=BTC&metric=dvol&interval=15m|1d&days=N","description":"Self-collected options time series (no synthetic backfill); allowlisted metrics; maturity + methodologyVersion in every response.","fields":"series[], maturity, methodologyVersion, firstObservedAt, observations, start, end, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/volume-quality","params":"","description":"Reported vs observable CEX volume signals with separate data-confidence scoring. sweepsInWindow counts the last sweepWindowDays UTC days, not the lifetime total — use volume-quality-history for a longer count. unassessedTopVenues names the top-20-by-reported-volume venues that no sweep measures, with the reason.","fields":"sweep.venues[], maturity, methodologyVersion, datasetStart, firstSweepAt, sweepsInWindow, sweepWindowDays, sweepCountScope, unassessedTopVenues[].{venue,reportedVolume24hUsd,rankByReportedVolume,reason}, unassessedRankSource, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/rwa-markets","params":"","description":"RWA perp markets: stocks / forex / commodities across venues. platforms[].funding is an hourly rate fraction; null when the venue or its interval is unknown.","fields":"markets[], updatedAt","public":true},{"path":"/api/data/mica","params":"","description":"Committed ESMA MiCA register snapshot joined to PerpFinder venue status, service permissions, EU-derivatives scope and fee context.","fields":"register, scope, coverage, authorized[], tracked[], dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources, ETag","public":true},{"path":"/api/data/premium","params":"","description":"Binance USDT-M perpetual premium index — (mark − index) / index, single venue. indexPrice is Binance’s own index, not an independent spot reference.","fields":"entries[].{symbol,venue,markPrice,indexPrice,premium,fundingRate}, avgPremium, venue, updatedAt, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/fear-greed","params":"","description":"Fear & Greed index (alternative.me, attributed). current is null when the index is unavailable.","fields":"current.{value,classification,timestamp}, history[], updatedAt, staleSince, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources","public":true},{"path":"/api/data/funding-history","params":"?asset=BTC&type=aggregates|venue|realized&days=7&venue=Binance&rateType=current|predicted&methodologyVersion=1|2|3|4&format=csv","description":"Self-collected funding history: aggregates, per-venue sweeps, or the append-only realized-settlement ledger. Rate types never mixed; no synthetic backfill. Sweep history defaults to one joined series: v2 sweeps up to the first v3 sweep (2026-09-23), then v3 up to the first v4 sweep (2026-09-25), then v4 (selectionMode \"joined\", methodologyVersions [2,3,4], seriesNote, excludedFields). Hourly rates are comparable across the join; v2 Aster and Crypto.com rawRate/rawIntervalMinutes are null; v2/v3 Hyperliquid predicted nextSettlementAt is the venue-reported start of the running hour, v4 points at the next settlement. methodologyVersion=1, 2, 3 or 4 selects one stored version only. Each version has its own dataset start.","fields":"series[]/entries[], coverage, maturity, methodologyVersion, methodologyVersions, selectionMode, seriesNote?, excludedFields?, datasetStart, dataStatus, generatedAt, schemaVersion, sources, ETag","public":true},{"path":"/api/data/funding-prediction-accuracy","params":"?format=json|csv&detail=pairs","description":"Funding prediction accuracy per venue and asset: stored predicted rates matched to the append-only realized-settlement ledger over one shared window per venue and asset (after the first usable stored prediction, up to the furthest targeted settlement, inside a 30-day read window). Accuracy (MAE and bias in bps per hour of the hourly-normalized rate, sign hit rate, median lead) is returned only when the publication gate passes (>=3 venues x >=30 settlements x >=7 days, <=30% missing); otherwise publication \"withheld\", accuracy null and the CSV returns 409. Hyperliquid v1-v3 predictions carry a labelled +1 interval settlement-time correction (horizonCorrection).","fields":"publication, gate.{ready,missing}, requirements, readWindow, methodologyVersions, method[], units, readiness[], accuracy[]|null, csv|null, dataStatus, generatedAt, schemaVersion, sources, ETag","public":true},{"path":"/api/data/volume-quality-history","params":"?days=7&venue=&format=csv","description":"Volume-quality sweep history per venue (reported vs observable signals over time). Measurements, never accusations.","fields":"series[], maturity, methodologyVersion, datasetStart, updatedAt, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/volume-ranking","params":"?view=ranking|share|share-monthly&window=24h|7d&date=YYYY-MM-DD&format=csv","description":"Perpetual volume ranking of CEX and DEX venues, reported and adjusted. Adjusted is the reported figure with held-out venues removed (unverified tier, 3x spike rule, failed depth test); it is not a modelled estimate. Each held-out venue keeps its reported figure and a dated reason. view=share gives the daily DEX share, raw and adjusted; view=share-monthly the volume-weighted monthly share. date pins one stored day file for citation. Measurements, not accusations.","fields":"ranking.{window,dates,capturedAt,reported,adjusted,gapUsd,gapShare,venues[].{name,type,reportedUsd,adjustedUsd,reportedRank,adjustedRank,holdOuts[].{rule,reason},spikeMultiple,depth}}, share[], monthly[], dayFile, permalink, depthSweepAt, datasetStart, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources","public":true},{"path":"/api/data/venue-history","params":"?venue=Binance&days=30&format=csv","description":"Per-venue daily volume/OI history from the committed snapshot series (since 2026-06-05) — venue-reported figures, normalized; null never zero-filled. The window is a calendar window, and every day with no capture is listed.","fields":"series[].{date,observedAt,backfilled,volume24h,volume7d,volume30d,openInterestUsd,perpPairs}, venueSlug, datasetStart, windowStart, windowEnd, windowDays, missingDays, gaps[], missingDates[], note, updatedAt, dataStatus, generatedAt, schemaVersion, sources","public":true},{"path":"/api/data/builder-fees","params":"?format=json|csv","description":"Builder fees that wallets and trading apps add to Hyperliquid perps fills, summed from the public Hyperliquid builder-fill files over the newest stored window of up to 7 UTC days. Each row gives the app, its builder addresses, notional, builder fees, the added fee in bps, and the base-tier taker total against a direct Hyperliquid order on $10,000. The same rows as the /trading-apps table. A missing value is null in JSON and empty in the CSV.","fields":"window.{from,to,dates}, directTakerBps, costModel, rows[].{app,builderAddresses,daysCaptured,fills,notionalUsd,builderFeesUsd,addedFeeBps,takerTotalBps,taker10kUsd,premiumOverDirectPct}, updatedAt, dataStatus, generatedAt, upstreamTimestamp, schemaVersion, sources","public":true},{"path":"/api/data/cost-history","params":"?market=perp&asset=BTC&size=100000&days=7|all&endDate=YYYY-MM-DD&methodologyVersion=1|2|3|4|5|6|7|8|active|all&venue=&format=json|csv","description":"Execution-cost history by methodology version. While the active version has fewer than 7 days of stored sweeps, the default merges every stored version (selectionMode \"merged\"); each point still carries its own methodologyVersion and the boundary sweeps are flagged. methodologyVersion=active is the strict active-only series. Use endDate to page an older window.","fields":"series[].{attemptId,ingestedAt,collectedAt,methodologyVersion,versionBoundary,side,feeType,feeTierAssumption,engineDataStatus,coverage,venues[].{halfSpreadBps,priceImpactBps,quoteStatus,slippageModel,executionModel,fillStatus,depthConfidence,depthFetchedUsd}}, lastSampleAgeMinutes, collectorStale, selectionMode, methodologySelectionNote, activeMethodologyMinDays, selectedMethodologyVersions, availableMethodologyVersions, versionBoundaries, globalDatasetStart, datasetStart, maturity, maturityByMethodology, venueCoverage, updatedAt, generatedAt","public":true}]}