{"openapi":"3.1.0","info":{"title":"Plexa API","version":"1.0.0","description":"Economic-safety API for trading agents: executable (realizable) DEX quotes and pre-trade token verdicts, paid per-call via x402 v2 (USDC, no API key). Informational data, not financial advice. First call from a new wallet is FREE — the full response, every field, same engine as a paid call. No trial tier, no reduced answer: only the COUNT is limited (one per wallet, across BOTH endpoints). Sign the x402 payment as usual; nothing is settled on-chain for that first call. P82 — you do not have to take that on trust: every 200 response carries `freeTrialApplied` — true when THAT call was served free, false when it was billed.","contact":{"name":"Plexa","url":"https://getplexa.com","email":"support@getplexa.com"}},"servers":[{"url":"https://api.getplexa.com"}],"paths":{"/v1/quote":{"post":{"operationId":"quote","summary":"Executable swap quote at size ($0.02 per call, x402)","description":"REALIZABLE fill price for the full requested size (not a mid/spot feed): executablePrice, priceImpactBps, depthAtSize, worstCaseSlippageBps, per-leg route, confidence — from canonical on-chain quoters on Base/Polygon/Arbitrum. Routing: the answer is the best SINGLE route — direct pools plus one-hop routes through the chain's major assets. We do not split an order across venues, and an aggregator that DOES split can therefore pay more than we quote: on a trapped token we saw its fill come out as our own best route PLUS our own second-best route added together, so treat our number as the best single road, not as the ceiling of the market. When that route pays less than 90% of the position (or no route exists at all), we ENUMERATE the token's counter-assets from chain logs — the same enumeration the exit-liquidity pot uses — and try up to 4 of them, most pools first, including the chain's NATIVE currency (address(0) pools in Uniswap v4, which no factory reports). In the pre-trade check that search also runs when the exit pot comes out under 5% of the position: a position you cannot get out of is a reason to ask whether we bought it by the right road. That search has its own time budget: if it does not finish, the answer is the best route found without it, never an error. Gas conditions: prices here are measured with a REAL trade's gas limit (12,000,000 units), not with the node's default (the block gas limit) — some Uniswap v4 hooks set their fee from the gas available to the caller (we measured one charging 0% above ~18.7M gas and 9% below), so a quote taken with the node default can promise what no trade can get; a venue whose quote does not fit that limit is dropped from the answer instead of being quoted under conditions a trade cannot reproduce. flags[].code vocabulary (closed list): NO_ROUTE — no venue we cover could fill this pair at this size — the answer carries no price, not a bad one · SINGLE_POOL — priced by ONE venue: no independent cross-check of the number exists in this answer · THIN_LIQUIDITY — the book is thin relative to your size — the fill moves the price a lot · SOURCE_DIVERGENCE — the venues we asked disagree with each other; on a pair with both a deep pool and dust pools this is normal dispersion, not proof of error · HIGH_IMPACT — price impact above 500 bps at THIS size — the size is the cause, not the token · MULTI_HOP_ONLY — no direct pool exists; the route goes through an intermediate token, so two fees and two impacts apply · SPOT_REFERENCE_DEGRADED — no venue offered a mid we can defend against the executable price, so spotPrice, priceImpactBps and worstCaseSlippageBps are NULL rather than guessed · DEGENERATE_POOL_EXCLUDED — a pool offering more output than the whole supply of the output token was dropped from the route set (reason `pool-degenerate-price`) — it is not a price, it is broken pool state · MARKET_DIVERGENCE — our output differs from an independent aggregator by more than the threshold; see marketRoute and divergenceBps for their number and the gap · ROADS_UNREAD — the road search could not enumerate every source of this token's pairs — a road may exist and stay untried, so this price is the best of what we could reach, not proof of the best that exists · ROAD_SEARCH_OVER_BUDGET — the road search ran out of its time budget before finishing — same meaning as ROADS_UNREAD, with the cause named · ROAD_SEARCH_NOT_RUN — the direct route already paid enough, so no road search was run: we did not look for an exotic road that might pay more. severity is info|warn|critical and describes how much the flag should weigh, not how bad the token is.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tokenIn","tokenOut"],"additionalProperties":false,"anyOf":[{"required":["sizeIn"]},{"required":["sizeUSD"]}],"properties":{"tokenIn":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"tokenOut":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"sizeIn":{"type":"string","pattern":"^(?:0\\.\\d*[1-9]\\d*|[1-9]\\d*(?:\\.\\d+)?)$","maxLength":78},"sizeUSD":{"type":"string","pattern":"^(?:0\\.\\d*[1-9]\\d*|[1-9]\\d*(?:\\.\\d+)?)$","maxLength":78},"chain":{"type":"string","enum":["base","polygon","matic","arbitrum","arbitrum-one","arb","eip155:8453","eip155:137","eip155:42161"]}}},"example":{"tokenIn":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","tokenOut":"0xE014d2A4da6E450f21b5050120D291e63c8940FD","sizeUSD":"5000","chain":"base"}}}},"responses":{"200":{"description":"Executable quote for the full requested size","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"amountIn":{"type":"string","description":"atomic units priced"},"amountOut":{"type":"string","description":"atomic units realizable at size"},"executablePrice":{"type":"number","description":"REALIZABLE fill price (tokenOut per tokenIn) at the requested size — not a mid/spot feed"},"spotPrice":{"type":["number","null"],"description":"Size-independent mid of the deepest qualifying venue. P16: null when no defensible mid exists (a pool with no in-range liquidity still quotes a slot0 mid; we publish absence rather than that number)."},"priceImpactBps":{"type":["number","null"],"description":"Derived from spotPrice — null exactly when spotPrice is null."},"depthAtSize":{"type":"number"},"worstCaseSlippageBps":{"type":["number","null"],"description":"Measured against spotPrice — null exactly when spotPrice is null."},"route":{"type":"object","description":"per-leg execution route (dex/pool/fee tier)"},"confidence":{"type":"string","enum":["high","medium","low"]},"flags":{"type":"array","description":"flags[].code vocabulary (closed list): NO_ROUTE — no venue we cover could fill this pair at this size — the answer carries no price, not a bad one · SINGLE_POOL — priced by ONE venue: no independent cross-check of the number exists in this answer · THIN_LIQUIDITY — the book is thin relative to your size — the fill moves the price a lot · SOURCE_DIVERGENCE — the venues we asked disagree with each other; on a pair with both a deep pool and dust pools this is normal dispersion, not proof of error · HIGH_IMPACT — price impact above 500 bps at THIS size — the size is the cause, not the token · MULTI_HOP_ONLY — no direct pool exists; the route goes through an intermediate token, so two fees and two impacts apply · SPOT_REFERENCE_DEGRADED — no venue offered a mid we can defend against the executable price, so spotPrice, priceImpactBps and worstCaseSlippageBps are NULL rather than guessed · DEGENERATE_POOL_EXCLUDED — a pool offering more output than the whole supply of the output token was dropped from the route set (reason `pool-degenerate-price`) — it is not a price, it is broken pool state · MARKET_DIVERGENCE — our output differs from an independent aggregator by more than the threshold; see marketRoute and divergenceBps for their number and the gap · ROADS_UNREAD — the road search could not enumerate every source of this token's pairs — a road may exist and stay untried, so this price is the best of what we could reach, not proof of the best that exists · ROAD_SEARCH_OVER_BUDGET — the road search ran out of its time budget before finishing — same meaning as ROADS_UNREAD, with the cause named · ROAD_SEARCH_NOT_RUN — the direct route already paid enough, so no road search was run: we did not look for an exotic road that might pay more. severity is info|warn|critical and describes how much the flag should weigh, not how bad the token is.","items":{"type":"object","properties":{"code":{"type":"string","enum":["NO_ROUTE","SINGLE_POOL","THIN_LIQUIDITY","SOURCE_DIVERGENCE","HIGH_IMPACT","MULTI_HOP_ONLY","SPOT_REFERENCE_DEGRADED","DEGENERATE_POOL_EXCLUDED","MARKET_DIVERGENCE","ROADS_UNREAD","ROAD_SEARCH_OVER_BUDGET","ROAD_SEARCH_NOT_RUN"]},"severity":{"type":"string","enum":["info","warn","critical"]},"detail":{"type":"string"}}}},"blockNumber":{"type":"string"},"decimals":{"type":"object"},"disclaimer":{"type":"string"},"ts":{"type":"number"},"validUntil":{"type":"number","description":"Epoch ms until which asking again returns THIS answer: ts + the freshness window of the shortest-lived input (pool state). It is a statement about our recomputation, NOT a promise that the price has not moved."}}},"example":{"chain":"base","tokenIn":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","tokenOut":"0xE014d2A4da6E450f21b5050120D291e63c8940FD","amountIn":"5000000000","amountOut":"8527353400367068025255029","executablePrice":1705.4706800734136,"spotPrice":1784.2047961927403,"priceImpactBps":441.2840739321799,"depthAtSize":8527353.400367068,"worstCaseSlippageBps":441.2840739321799,"route":{"dex":"split","path":["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2","0xE014d2A4da6E450f21b5050120D291e63c8940FD"],"pools":["0xa41Bc0AFfbA7Fd420d186b84899d7ab2aC57fcD1","0xCc68Cb8B514A2216D2eECe3A0e8597Ce483610eb"],"hop":"0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2","legs":[{"dex":"slipstream","venue":"aerodrome-cl-1","pool":"0xa41Bc0AFfbA7Fd420d186b84899d7ab2aC57fcD1","tokenIn":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","tokenOut":"0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2","feePips":1},{"dex":"aerodrome","venue":"aerodrome","pool":"0xCc68Cb8B514A2216D2eECe3A0e8597Ce483610eb","tokenIn":"0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2","tokenOut":"0xE014d2A4da6E450f21b5050120D291e63c8940FD","stable":false}]},"confidence":"low","flags":[{"code":"SOURCE_DIVERGENCE","severity":"warn","detail":"venues disagree by 1217 bps"},{"code":"HIGH_IMPACT","severity":"warn","detail":"price impact 441 bps"},{"code":"SPOT_REFERENCE_DEGRADED","severity":"warn","detail":"1-hop route: spot is composed from both legs, not a single reference venue"}],"venuesConsidered":7,"marketRoute":{"source":"vendor:kyberswap","amountOut":"8527510842112259565932282","impactBps":449,"splitTop":[{"venue":"aerodrome","share":50},{"venue":"sectorone-v20","share":26},{"venue":"aerodrome-cl","share":18},{"venue":"uniswap-v4-fairflow","share":6}]},"marketRouteUnavailable":null,"divergenceBps":0,"singleRouteOnly":false,"blockNumber":"51728981","decimals":{"in":6,"out":18},"disclaimer":"Informational on-chain liquidity data, not financial advice. Prices reflect pool state at the stated block and may move before execution.","ts":1790247318433,"validUntil":1790247321433}}}},"400":{"description":"Invalid input (strict schema: 0x addresses; at least one of sizeIn/sizeUSD — if both are provided, sizeUSD takes precedence). Body includes detail + exampleRequest + docs; rejected requests are never charged."},"402":{"description":"Payment required (x402 v2). The payment requirements (amount, USDC asset, payTo, accepted networks) are base64-JSON-encoded in the PAYMENT-REQUIRED response header. Sign an EIP-3009 USDC authorization (EVM networks) or submit a partially-signed SPL USDC transfer transaction (Solana) and retry the same request with the PAYMENT-SIGNATURE header (npm @x402/fetch automates this). The JSON body is an informative summary only — the header is authoritative.","headers":{"PAYMENT-REQUIRED":{"description":"base64(JSON) x402 v2 payment requirements: {x402Version, resource, accepts[]}","schema":{"type":"string"}}}},"429":{"description":"Rate limited"}}}},"/v1/pretrade/check":{"post":{"operationId":"pretradeCheck","summary":"Pre-trade economic-safety verdict ($0.05 per call, x402)","description":"Two-level economic-safety answer for an ERC-20. Served on: base, polygon, arbitrum. Per network — base (13 liquidity factories + uniswap-v4/pancakeswap-infinity, priced on uniswap-v3/aerodrome/aerodrome-cl-1/aerodrome-cl-2/aerodrome-cl-3/sushiswap-v3/uniswap-v2/sushiswap-v2/pancakeswap-v2/baseswap/alienbase/swapbased/uniswap-v4); polygon (15 liquidity factories + uniswap-v4, priced on uniswap-v3/sushiswap-v3/quickswap-v3/quickswap-v2/uniswap-v2/sushiswap-v2/apeswap/uniswap-v4); arbitrum (10 liquidity factories + uniswap-v4, priced on uniswap-v3/sushiswap-v3/ramses-v3/camelot-v3/sushiswap-v2/camelot-v2/uniswap-v2/uniswap-v4). The exit pot and the quote are measured on DIFFERENT venue lists by design: the pot only needs pool discovery and balances, a quote needs a quoter we have confirmed against the live market. Venues that count toward the exit pot but are NOT in the price: base — pancakeswap-v3, pancakeswap-infinity; polygon — retro, ramses-v3, w-dex, dooar, vulcandex, fraxswap, wault, polycat; arbitrum — pancakeswap-v3, ramses-v2, solidly-v3. On those the quote can be worse than the market while the safety verdict still sees that liquidity. A network that is not listed answers 422 — we do not publish a verdict where we have not measured the exit. Level 1 — verdict avoid|clear|unknown: \"avoid\" = a listed trap was PROVEN at this block (see `triggers`); \"clear\" = none of them fired AND the liquidity sweep reached a conclusion; \"unknown\" = none fired but the sweep did NOT reach a conclusion (`liquidityCoverage.conclusive: false`), so absence of a trap is not established — see the `exit-coverage-incomplete:<what>` line in `reasons`. \"clear\" is NOT a safety rating and NOT a prediction — structural risk lives in `risk_profile`. The trap list is closed: NO_EXIT_VENUE, EXIT_LIQUIDITY_DRAINED, TRADING_DISABLED. Level 2 — risk_profile: age, holder concentration (ANY token age: top-1/top-10 share computed by us from balances + on-chain totalSupply; data age in the response; vendor outage → \"unknown\" with a reason, never a clean default), liquidity structure incl. exitLiquidityUsd (since 20.09.2026 this is what SELLING THE POSITION returns: we quote the sale of the very position this answer prices on the direct road, and take the BEST road against the counter-asset roads the second hop measures — never their sum. exitPotBasis says which one you got: \"position-sale\" = measured proceeds, \"pool-inventory\" = that sale could not be quoted this call, so the number falls back to what the pools HOLD. The old meaning is still published, as exitPoolInventoryUsd — an upper bound, not a promise; venues whose canonical quoter we could not confirm are reported separately in exitPotUnquotedUsd instead of being summed in), oracle availability, transfer restrictions — as measured DATA with plain-language notes, not severities. Plus confidence, reasons, the 5 raw signals and an executable quote sub-result. confidence: On \"avoid\" this is confidence IN THE TRIGGER, which is a measurement taken this call, so it is always \"high\" — a check that failed elsewhere does not make the measured trap less true. On \"clear\" it is how COMPLETE the checks were: fewer axes computed, lower confidence. On \"unknown\" it is capped at \"low\" by construction: the check the verdict depends on did not finish, so a high number there would contradict the verdict word next to it. Either way the gaps are reported explicitly — see `reasons` and the null fields in `risk_profile`. Gas conditions: prices here are measured with a REAL trade's gas limit (12,000,000 units), not with the node's default (the block gas limit) — some Uniswap v4 hooks set their fee from the gas available to the caller (we measured one charging 0% above ~18.7M gas and 9% below), so a quote taken with the node default can promise what no trade can get; a venue whose quote does not fit that limit is dropped from the answer instead of being quoted under conditions a trade cannot reproduce. Roads are named, not implied: exitLadderStatus describes ONLY the roads in exitLadderScope (\"uniswap-v4-direct\" — direct Uniswap v4 pools), while the road the pot was actually measured on is named in exitReachRoad (\"direct\" or \"via <asset>\"). They are often different, and \"unsellable\" beside a non-empty pot means exactly that, not \"this token cannot be sold\". For the same reason exitPoolInventoryUsd stops being an upper bound whenever the v4 ladder ran (its v4 share is then the ladder's reach, not inventory) and it never includes the second leg of a two-leg sale. verdict semantics changed 2026-08-01 (v2): avoid = provable trap only; ok/caution are gone. 2026-08-27 (P67): a THIRD value \"unknown\" was added — it takes over the cases that used to answer \"clear\" while `liquidityCoverage.conclusive` was false. No existing value changed meaning; code branching on \"avoid\" is unaffected, and code branching on \"clear\" now gets strictly fewer, better-founded clears. 2026-09-21 (P96): a clear verdict now also requires the MEASURED sale of your position to return at least 90% of the size you asked about. Below that the answer is \"unknown\" with the reason exit-below-90pct — no trap was proven, but the exit we measured is not there at this size. Again strictly fewer clears; avoid is untouched. Alias paths for /v1/pretrade/check: /v1/token-safety, /v1/rug-check — the SAME endpoint (same engine, same price, same request and response, one shared free trial), not a different product. They exist because agent catalogs index by URL path.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"additionalProperties":false,"properties":{"token":{"type":"string","pattern":"^0x[0-9a-fA-F]{40}$"},"sizeUSD":{"type":"string","pattern":"^(?:0\\.\\d*[1-9]\\d*|[1-9]\\d*(?:\\.\\d+)?)$","maxLength":78},"chain":{"type":"string","enum":["base","polygon","matic","arbitrum","arbitrum-one","arb","eip155:8453","eip155:137","eip155:42161"]}}},"example":{"token":"0xE014d2A4da6E450f21b5050120D291e63c8940FD","sizeUSD":"1000"}}}},"responses":{"200":{"description":"Economic-safety verdict + executable quote sub-result","content":{"application/json":{"schema":{"type":"object","properties":{"chain":{"type":"string"},"token":{"type":"string"},"verdict":{"type":"string","enum":["avoid","clear","unknown"],"description":"\"avoid\" = a listed trap was PROVEN at this block (see `triggers`); \"clear\" = none of them fired AND the liquidity sweep reached a conclusion; \"unknown\" = none fired but the sweep did NOT reach a conclusion (`liquidityCoverage.conclusive: false`), so absence of a trap is not established — see the `exit-coverage-incomplete:<what>` line in `reasons`. \"clear\" is NOT a safety rating and NOT a prediction — structural risk lives in `risk_profile`."},"triggers":{"type":"array","items":{"type":"string","enum":["NO_EXIT_VENUE","EXIT_LIQUIDITY_DRAINED","TRADING_DISABLED"]},"description":"Which proven traps fired. Empty unless verdict is \"avoid\". This is the CLOSED list — nothing outside it can produce \"avoid\"."},"confidence":{"type":"string","enum":["high","medium","low"],"description":"On \"avoid\" this is confidence IN THE TRIGGER, which is a measurement taken this call, so it is always \"high\" — a check that failed elsewhere does not make the measured trap less true. On \"clear\" it is how COMPLETE the checks were: fewer axes computed, lower confidence. On \"unknown\" it is capped at \"low\" by construction: the check the verdict depends on did not finish, so a high number there would contradict the verdict word next to it. Either way the gaps are reported explicitly — see `reasons` and the null fields in `risk_profile`."},"reasons":{"type":"array","items":{"type":"string"}},"risk_profile":{"type":"object","description":"Structural risk as DATA, not as a judgement: age, concentration, liquidity (incl. exitLiquidityUsd — since 20.09.2026 it is what SELLING THE POSITION returns: we quote the sale of the position this answer prices on the direct road and take the BEST road against the counter-asset roads of the second hop, never their sum; exitPotBasis says whether you got measured proceeds (position-sale) or the fallback to what the pools hold (pool-inventory), and the old meaning is published as exitPoolInventoryUsd), oracle availability, transfer restrictions. Each section carries measured fields plus a plain-language `note`. Absent numbers are null (could not measure), never 0. Roads are named, not implied: exitLadderStatus describes ONLY the roads in exitLadderScope (\"uniswap-v4-direct\" — direct Uniswap v4 pools), while the road the pot was actually measured on is named in exitReachRoad (\"direct\" or \"via <asset>\"). They are often different, and \"unsellable\" beside a non-empty pot means exactly that, not \"this token cannot be sold\". For the same reason exitPoolInventoryUsd stops being an upper bound whenever the v4 ladder ran (its v4 share is then the ladder's reach, not inventory) and it never includes the second leg of a two-leg sale. `risk_profile.concentration` carries `ageSec` and `stale`. `ageSec: null` with `stale: false` means the holder data was read on this call. A number in `ageSec` means it was measured that many seconds ago; `stale: true` additionally means the holder source was unreachable right now, so the LAST KNOWN measurement is reported instead of nothing, and `confidence` drops. `stale: null` means there is no holder value at all in this response — neither fresh nor stored — so there is nothing for the freshness flag to describe. The stored value survives a restart and keeps its real age. Concentration is level-2 structural data — no verdict trigger reads it — so an aged value cannot change `avoid`/`clear`. P106 (2026-10-01): concentration.top1SharePct / top10SharePct are computed WITHOUT pool contracts (singleton managers such as the Uniswap v4 PoolManager, and the pools our route search found); the previous numbers, with pools counted as holders, are top1SharePctInclPools / top10SharePctInclPools.","properties":{"concentration":{"type":"object","properties":{"top1SharePct":{"type":["number","null"],"description":"P106: share of supply (%) held by the largest holder that is NOT a pool contract. Pools removed: the chain's singleton managers (Uniswap v4 PoolManager, PancakeSwap Infinity vault) and every pool our route search found on this call. Before 2026-10-01 pools were counted as holders — that number is top1SharePctInclPools. null = no holder data, or the holder rows carry no addresses (poolsExclusion: \"not-applied\")."},"top10SharePct":{"type":["number","null"],"description":"P106: share of supply (%) held by the ten largest non-pool holders. A FLOOR when top10Bound is \"lower\"."},"holders":{"type":["number","null"],"description":"Number of holding addresses, pools included. null = unknown (the holder source returned a full page)."},"holdersExact":{"type":["boolean","null"],"description":"true = `holders` is an exact count."},"source":{"type":["string","null"],"description":"Holder source: \"graph\" (indexed holders vendor, top 10 rows) or \"replay\" (our on-chain transfer replay)."},"asOfBlock":{"type":["number","null"],"description":"Block the holder data describes."},"ageSec":{"type":["number","null"],"description":"null = read on this call; otherwise how many seconds ago it was measured."},"stale":{"type":["boolean","null"],"description":"true = live sources were unreachable and this is the last known value; null = nothing to describe."},"poolsExclusion":{"type":["string","null"],"enum":["applied","singletons-only","not-applied"],"description":"P106: what was done about pools. \"applied\" = holder addresses were matched against the pools this call's route search found (venues that did not answer contribute none — see liquidityCoverage.venuesUnread) and the chain's singleton managers. \"singletons-only\" = the liquidity axis failed outright and produced no pool list, so only the singleton managers were removed and other pool contracts may still count. \"not-applied\" = the holder rows carry no addresses (a measurement cached before 2026-10-01): top1/top10 are null and the old numbers are in *InclPools. null = no concentration at all."},"poolsExcluded":{"type":["number","null"],"description":"P106: how many pool addresses were found AMONG the listed holders and removed. null = exclusion not applied."},"poolsExcludedAddresses":{"type":"array","items":{"type":"string"},"description":"P106: those pool addresses."},"poolsSharePct":{"type":["number","null"],"description":"P106: share of supply (%) they hold — liquidity, not a position. A floor when the holder list is limited (vendor: 10 rows)."},"top1SharePctInclPools":{"type":["number","null"],"description":"P106: the previous meaning of top1SharePct — pool contracts counted as holders."},"top10SharePctInclPools":{"type":["number","null"],"description":"P106: the previous meaning of top10SharePct — pool contracts counted as holders."},"top10Bound":{"type":["string","null"],"enum":["exact","lower"],"description":"P106: \"exact\" = top10SharePct sums ten non-pool holders (or all there are). \"lower\" = the holder source lists a limited number of addresses (vendor: 10) and fewer than ten non-pool holders remained after removing pools — the number is a floor."},"note":{"type":"string","description":"Plain-language reading, including which pools were removed and the numbers with pools counted."}}}}},"flags":{"type":"object","description":"5 raw signals: F-LIQ, F-CONC, F-AGE, F-FOT, O-SANITY — keys of this object, in plain words: F_LIQ = exit liquidity (which pools hold this token and what selling the position returns); F_CONC = holder concentration (the share of supply held by the largest holders); F_AGE = token age (the block of its first transfer); F_FOT = transfer restrictions (tax, blacklist, max-transaction limits, the trading gate); O_SANITY = independent price cross-check (a Chainlink feed, or a second venue pricing the same pair). When an axis could not be computed, `reasons` says so as \"not checked: <what> — <why>\" — the key itself never appears in the text."},"quote":{"type":["object","null"],"description":"executable USDC→token quote at sizeUSD, or null if unpriceable"},"sizeUSD":{"type":"string"},"disclaimer":{"type":"string"},"ts":{"type":"number"},"validUntil":{"type":"number","description":"Epoch ms until which asking again returns THIS answer: ts + the freshness window of the shortest-lived input the answer rests on (pool state, which feeds the exit pot). A statement about our recomputation, not about the market."},"coverage":{"type":"object","description":"How complete this answer is, in one comparison: axesReporting of axesExpected axes produced a result. The detail stays where it was — `reasons`, `flags[].severity === \"unknown\"` and the null fields of `risk_profile`.","properties":{"axesExpected":{"type":"number"},"axesReporting":{"type":"number"}}},"identity":{"type":"object","description":"ERC-20 identity read straight from the token contract (P50). Every field here is measured by us, not proxied from a data provider.","properties":{"name":{"type":["string","null"],"description":"ERC-20 name() read from the contract. null = the call did not answer."},"symbol":{"type":["string","null"],"description":"ERC-20 symbol() read from the contract. null = the call did not answer."},"decimals":{"type":["number","null"],"description":"ERC-20 decimals() read from the contract."},"totalSupplyRaw":{"type":["string","null"],"description":"totalSupply() in ATOMIC units, as a string — a uint256 does not survive a JSON number."},"totalSupply":{"type":["number","null"],"description":"totalSupply in human units (needs decimals). This is THIS CHAIN's supply: for a bridged token it is smaller than the global figure a market-data site shows."},"note":{"type":"string","description":"Plain-language summary, including which reads did not answer."}}},"valuation":{"type":"object","description":"Fully-diluted value computed from OUR executable quote and the contract's supply (P50).","properties":{"fdvExecutableUsd":{"type":["number","null"],"description":"Fully-diluted value at the EXECUTABLE price for your sizeUSD, not at spot. Lower than a spot-based FDV on thin books, and based on this chain's totalSupply. null = no quote or no supply."},"basis":{"type":["string","null"],"description":"The formula actually used, so the number can be recomputed."},"note":{"type":"string","description":"Why this figure can legitimately differ from a market-data site."}}},"ownership":{"type":"object","description":"Ownership and mintability read from the chain (P50). Absent answers stay null: unknown ownership is never reported as renounced.","properties":{"ownerAddress":{"type":["string","null"],"description":"owner()/getOwner(). null = neither answered — unknown, NOT renounced."},"ownerRenounced":{"type":["boolean","null"],"description":"true = owner is the zero address. null = ownership unknown."},"isMintable":{"type":["boolean","null"],"description":"A known mint selector is present in the bytecode. Heuristic: presence is not proof it is callable, and absence is not proof of fixed supply (proxies, assembly dispatchers)."},"creatorAddress":{"type":["string","null"],"description":"Sender of the token's FIRST transfer — a creator candidate, not a proven deployer."},"creatorBalance":{"type":["number","null"],"description":"That address's current balance, human units."},"creatorSharePct":{"type":["number","null"],"description":"That balance as a percentage of totalSupply."},"note":{"type":"string","description":"Plain-language reading, including the caveats above."}}},"dormancy":{"type":"object","description":"How long the large holders have sat still (P50), from the same holder axis as concentration. Absent when that axis produced nothing.","properties":{"topHolderIdleDays":{"type":["number","null"],"description":"Days since ANY top holder's balance last changed, from real block timestamps. null = the holder axis produced no block, so this is absent rather than zero."},"lastTopHolderMoveBlock":{"type":["number","null"],"description":"The block of that last change."},"headBlock":{"type":["number","null"],"description":"Chain head the measurement was taken against."},"note":{"type":"string","description":"Plain-language reading and its caveats."}}},"market":{"type":"object","description":"P52 — THIRD-PARTY market data: spot price, 24h volume and global market cap from DexScreener, holder count from GoPlus. Nothing in this block is measured by us, and `sources` says so field by field. Compare marketCapUsd with valuation.fdvExecutableUsd rather than equating them — they are different quantities.","properties":{"priceUsdSpot":{"type":["number","null"],"description":"SPOT price in USD from the deepest Base pool, as printed by DexScreener (vendor data, not ours). This is NOT the price your order gets — that is quote.executablePrice at your sizeUSD, which is worse than spot on a thin book. null = the vendor did not answer; the reason is in `sources`."},"volume24hUsd":{"type":["number","null"],"description":"DexScreener's 24h volume summed over the Base pairs where this token is the BASE asset. Pairs where it is the quote asset are not counted. null = unknown, never a silent zero."},"marketCapUsd":{"type":["number","null"],"description":"The vendor's GLOBAL market cap — all chains, their supply source. Deliberately NOT the same quantity as valuation.fdvExecutableUsd, which is THIS chain's supply at OUR executable price; for a bridged token ours is legitimately smaller. Compare them, do not equate them."},"holderCount":{"type":["number","null"],"description":"GoPlus's count of holding addresses on this chain. Contracts (pools, bridges, treasuries) are addresses too, so read it with the same caution as concentration."},"note":{"type":"string","description":"Plain-language reading, including what each number is not."}}},"sources":{"type":"object","description":"Provenance for EVERY field of this response. A map of path-prefix -> source, resolved by LONGEST matching prefix, with \"*\" as the default — so no field can be without a source. Four verbs: \"measured\" (we read it on-chain at this block), \"derived:<formula>\" (computed from other fields here), \"vendor:<name>\" (a third party said so), \"unavailable:<reason>\" (we tried and could not — the value is null). Example: {\"*\":\"measured\",\"risk_profile.concentration\":\"vendor:graph\",\"market.holderCount\":\"vendor:goplus\"}.","additionalProperties":{"type":"string"}},"observedExit":{"type":["object","null"],"description":"P106 (2026-10-01): executed sales through Uniswap v4 pools whose hook REJECTED our quote of the sale on this call. null = no hooked pool rejected the quote (the block is not computed). The verdict does not read it. pools[] items carry: poolId, hooks, hookFlags, counter, status, salesObserved, lastSaleBlock, largestSaleUsd, medianDeviationPct, hookSwapsExcluded, amountsBasis.","properties":{"basis":{"type":"string","enum":["v4-hook-refused-quote"],"description":"Why this block exists: a Uniswap v4 pool whose hook has swap permissions REJECTED our quoter's simulation of the sale. A hook can refuse third-party quoters while real sales still execute (Base, AROS, 2026-09: 12 holder sales in 7 days through such a pool, median 1.008% below the pool price — the 1% pool fee plus price impact). This block reads those executed sales. It never changes the verdict: past sales by others are not a measured sale of YOUR position now."},"status":{"type":"string","enum":["measured","not_measured","no_route","refused","unsellable","vendor_silent"],"description":"\"measured\" = the window was read for every pool asked; \"vendor_silent\" = the node did not return a pool's Swap logs (numbers are null — not \"no sales\"); \"not_measured\" = no answer block to anchor the window."},"windowFromBlock":{"type":["number","null"],"description":"First block of the window actually read."},"windowToBlock":{"type":["number","null"],"description":"Last block of the window (the answer block)."},"salesObserved":{"type":["number","null"],"description":"Holder sales summarized: PoolManager Swap events of the refusing pool(s) where the token went INTO the pool and the event sender is not the pool's own hook. At most the latest 20, within at most 7 days. 0 with status measured = the window was read and holds no sale."},"salesCapped":{"type":"boolean","description":"true = more sales exist (or may exist) in the window than the 20 summarized."},"lastSaleBlock":{"type":["number","null"],"description":"Block of the latest sale."},"largestSaleUsd":{"type":["number","null"],"description":"Largest sale in USD: counter asset received x the counter asset's USD price at the ANSWER block (the same price the exit pot uses), not at the sale's block."},"medianDeviationPct":{"type":["number","null"],"description":"Median over the summarized sales of (1 - (counter received / token sold) / pool price just before that sale) x 100. Positive = the seller got less than the pool price; pool fee and price impact are inside. The price before a sale is the sqrtPriceX96 of the pool's previous Swap event (only swaps move a v4 price); for the first event of the window, StateView.getSlot0 one block earlier."},"amountsBasis":{"type":"string","enum":["swapper-exact","pool-leg-only"],"description":"\"pool-leg-only\" if any asked pool's hook may return deltas (then the event amounts can differ from what the seller got)."},"poolsRefused":{"type":"number","description":"Hooked Uniswap v4 pools that rejected our quote on this call."},"poolsNotRead":{"type":"number","description":"Of those, how many were not read (at most 3 pools are read)."},"pools":{"type":"array","items":{"type":"object"},"description":"Per pool, the same numbers (schema: observedExit.pools[] properties)."}}},"liquidityCoverage":{"type":"object","description":"It also carries `liquidityCoverage` {conclusive, poolsFound, factoriesChecked, unmeasuredVenues, unmeasuredVenueNames, venuesUnread, singletonPoolsSeen, singletonPoolsCounted, singletonPoolsRejected, singletonPoolsHooked, singletonPoolsHookRefused, singletonHookFlags, singletonScanTruncated, secondHopAssetsSeen, secondHopAssetsCounted, secondHopAssetsRejected, secondHopTruncated, secondHopUsd, secondHopAssets, exitPotBound, exitPotBoundReason, exitVenuesCounted, singletonPoolsDiscovered, singletonPoolsUnasked, exitLadderTopUsd, exitLadderBrokeAtUsd, exitLadderPoolsProbed, exitLadderStatus, exitLadderScope, secondHopStatus, exitPotUnquotedUsd, exitVenuesUnquoted, exitPotBasis, exitReachUsd, exitReachStatus, exitReachRoad, exitPoolInventoryUsd, asOfBlockFirst, asOfBlock}: `conclusive: true` with `poolsFound: 0` means every covered factory was queried and no pool exists — that is a measurement, and it is what raises NO_EXIT_VENUE. `conclusive: false` means an AMM we cannot measure pool-by-pool (Uniswap v4 and other singleton AMMs) holds this token, so the exit triggers are not raised on this call — and since P67 the verdict is then `unknown`, never `clear`: a sweep that did not reach a conclusion cannot report the absence of a trap. `poolsFound: null` with `factoriesChecked: 0` means discovery did not run. Roads out that are NOT the chain's stable/gas assets are covered too: `secondHopAssetsSeen` counts counter assets the factories list a pool for with this token (read from their own pool-creation events, so no list of `good` assets is involved), `secondHopAssetsCounted` how many of those roads we confirmed by quoting that asset's own exit, `secondHopAssetsRejected` how many we could not confirm (they add nothing AND make the exit inconclusive), `secondHopUsd`/`secondHopAssets` what they contributed and which assets carry it, `secondHopTruncated` whether more roads existed than the per-call cap. That search runs only when the stable/gas pot is below the drain floor — above it another road cannot change the answer. For singleton AMMs the sell is SIMULATED per pool, and the three outcomes are separate counts: `singletonPoolsCounted` (simulation succeeded, proceeds are inside exitLiquidityUsd), `singletonPoolsRejected` (the chain rejected the sale — a measurement about that pool, not a gap in our data), and pools left unquestioned because the scan hit its work cap, flagged by `singletonScanTruncated`. `singletonPoolsSeen` is the total found and `singletonPoolsHooked` how many run a hook inside the swap. All five are null only when the liquidity axis produced no metrics at all. `asOfBlockFirst` and `asOfBlock` are the Base block heights at the start and the end of the liquidity reads: equal means the axis was read inside one block and is reproducible at that block, different means no single block describes it and the gap is the size of that uncertainty.","properties":{"conclusive":{"type":"boolean","description":"Whether the exit check reached a CONCLUSION — i.e. whether we are entitled to state that no exit exists. false does not mean nothing was measured: the pools found and the pot are still in risk_profile.liquidity and are correct."},"poolsFound":{"type":["number","null"],"description":"Pools found on the covered factories. null = discovery did not run (NOT zero pools)."},"factoriesChecked":{"type":"number","description":"How many factories were queried. 0 = we did not look at all."},"unmeasuredVenues":{"type":"number","description":"Venues that hold this token but do not yield to our measurement."},"unmeasuredVenueNames":{"type":"array","items":{"type":"string"},"description":"Their identifiers."},"venuesUnread":{"type":["number","null"],"description":"Of those, venues that simply did not answer on THIS call (upstream node), as opposed to AMMs we cannot measure by design. Non-zero means retrying may return a complete answer. null = the liquidity axis produced no metrics at all."},"singletonPoolsSeen":{"type":["number","null"],"description":"Singleton-AMM pools of this pair found via the Initialize event (hooked ones included). null = the liquidity axis produced no metrics at all."},"singletonPoolsCounted":{"type":["number","null"],"description":"Of those, pools whose sell simulation SUCCEEDED — their proceeds are inside exitLiquidityUsd."},"singletonPoolsRejected":{"type":["number","null"],"description":"Of those, pools whose sell simulation was REJECTED by the chain. That is a measurement — this pool cannot be sold into — not a gap in our data."},"singletonPoolsHooked":{"type":["number","null"],"description":"Of those, pools whose hook address carries swap permissions, so the hook runs inside the sale. Derived from the address bits, no RPC call."},"singletonPoolsHookRefused":{"type":["number","null"],"description":"Of the REJECTED pools, those whose hook carries swap permissions: the chain said 'cannot sell here' AND a hook had the right to interfere. Distinguishes 'the hook forbade it' from 'the pool is empty'."},"singletonHookFlags":{"type":["string","null"],"description":"Comma-separated swap permissions held by the hooks of those refusing pools (BEFORE_SWAP, AFTER_SWAP, BEFORE_SWAP_RETURNS_DELTA, AFTER_SWAP_RETURNS_DELTA). null = no hooked pool refused."},"singletonScanTruncated":{"type":["boolean","null"],"description":"true = the singleton scan hit its work cap and some pools were left unqueried. Reported whether or not it changed the answer."},"secondHopAssetsSeen":{"type":["number","null"],"description":"P68. Counter assets other than the chain's own stable/gas assets (flags.F_LIQ.metrics.counterAssetsLabel names them) that the factories list a pool for with this token — i.e. how many OTHER roads out of the token exist at all. Enumerated from the factories' own pool-creation events, so no list of \"good\" assets is involved. Only computed when the stable/gas pot is below the drain floor: above it, another road cannot change the answer."},"secondHopAssetsCounted":{"type":["number","null"],"description":"Of those, the ones whose road we CONFIRMED: the counter asset has its own exit to USDC that our own engine quotes. Only confirmed roads add to exitLiquidityUsd."},"secondHopAssetsRejected":{"type":["number","null"],"description":"Counter assets we could NOT confirm (no pool found, balance unreadable, or the asset is not quotable by us). They add nothing to the pot AND make the exit inconclusive — never a silent zero."},"secondHopTruncated":{"type":["boolean","null"],"description":"true = more counter assets exist than the per-call cap, so the list was cut. Reported whether or not it changed the answer."},"secondHopUsd":{"type":["number","null"],"description":"How many USD of exitLiquidityUsd came from those confirmed second-hop roads. It is the BOTTLENECK of the two hops (what your position fetches on the road, capped by the counter asset's own exit to USDC), never their sum, and the position is sized by our own entry quote for this size."},"secondHopAssets":{"type":"array","items":{"type":"string"},"description":"The confirmed roads as `SYMBOL:usd` — which asset carries the exit and how much of it."},"exitPotBound":{"type":"string","enum":["measured","lower"],"description":"P83. What exitLiquidityUsd MEANS in this answer. \"measured\" = the sweep walked every source it knows about. \"lower\" = the sweep stopped once the answer to the drain question was already determined (or hit a work cap, or priced through a venue whose pools are not in the count), so the pot is AT LEAST this number and we do not claim how much more. Read with `conclusive`, which answers a different question: whether the VERDICT is safe to state. A `lower` pot with `conclusive: true` is consistent — unasked pools can only raise the pot, never lower it — but dividing a `lower` pot by your position size gives a floor, not a coverage ratio."},"exitPotBoundReason":{"type":["string","null"],"description":"Why the pot is a lower bound, venue by venue: which venue stopped the sweep, how many of its pools were asked out of how many exist, whether the second hop was searched at all, and any venue our own quote priced through that is not in exitVenuesCounted. null when exitPotBound is \"measured\"."},"exitVenuesCounted":{"type":"array","items":{"type":"string"},"description":"The venues whose pools actually contributed counter asset to exitLiquidityUsd. A venue that was visited but contributed nothing is not listed here."},"singletonPoolsDiscovered":{"type":["number","null"],"description":"P83. How many singleton (Uniswap v4) pools of this token the Initialize scan found — the denominator for singletonPoolsSeen. Without it, \"we asked 2\" and \"2 exist\" looked identical from outside."},"singletonPoolsUnasked":{"type":["number","null"],"description":"Of those, how many were never quoted because the sweep stopped early. Every unasked pool can only ADD to the pot, which is why the verdict stays safe while the number stays a floor."},"exitLadderTopUsd":{"type":["number","null"],"description":"P88. The LARGEST size, in USD, that we actually sold into a Uniswap v4 pool at a loss no worse than the drain floor (5% of the size sold) — a simulated sale per rung of a fixed dollar ladder ($5/$25/$100/$500/$2k/$10k/$50k, plus one geometric refinement). This is the v4 part of exitLiquidityUsd. Before P88 that part was a sale of YOUR size, so it was capped at about your size and a coverage ratio built on it could not exceed ~1 no matter how deep the pool was. null = the ladder did not run: the pot already answered the question (see exitPotBoundReason)."},"exitLadderBrokeAtUsd":{"type":["number","null"],"description":"P88. The first ladder rung whose loss went past the drain floor (or that the chain refused) — the size at which this pool stops being an exit. null WITH a non-null exitLadderTopUsd means the ladder ran out of rungs or work budget before the pool ran out of depth; exitPotBoundReason then carries `ladder-capped`, and the pot is a floor."},"exitLadderPoolsProbed":{"type":["number","null"],"description":"P88. How many v4 pools the ladder asked in addition to the main sweep, in discovery order and with hooked pools on equal terms — on two measured tokens the deepest pool was a HOOKED one that the main sweep's hookless-first order never reached. Add it to singletonPoolsSeen to get how many pools this answer actually questioned."},"exitLadderStatus":{"type":["string","null"],"enum":["measured","not_measured","no_route","refused","unsellable","vendor_silent"],"description":"P90. What exitLadderTopUsd MEANS — especially a zero, which used to carry three different facts. \"measured\": at least one v4 pool took a rung, the number is measured reach. \"unsellable\": pools answered the smallest ($5) rung with a number and every answer lost more than the drain floor — a measured inability to sell (KOTAEMON: 89% pool fee). \"refused\": no pool answered with a number and at least one reverted (hook/quoter). \"vendor_silent\": neither a number nor a revert — the node did not answer after retries, or the time budget ran out first. \"no_route\": nothing to ask — no v4 pool against a priced counter asset, or all of them empty. \"not_measured\": the ladder did not run (the pot already answered the question). null = the liquidity axis produced no metrics at all. \"unsellable\" blocks a `clear` verdict (see reasons)."},"exitLadderScope":{"type":["string","null"],"description":"P100. WHICH ROADS the ladder measured, so its status is never read wider than the measurement. Today always \"uniswap-v4-direct\": the ladder walks DIRECT Uniswap v4 pools and nothing else. exitLadderStatus: \"unsellable\" therefore means \"those pools answered and every answer lost more than the drain floor\" — it never means the token cannot be sold at all. Measured 22.09.2026 on DEUS (Base, block 51 611 525): \"unsellable\" across 31 v4 pools while selling the position returned $4 735.82 through Aerodrome into VIRTUAL and on into the dollar — a real swap simulated on the same block agreed to 0.0000%. The road behind the pot is named in exitReachRoad. null = the liquidity axis produced no metrics at all."},"secondHopStatus":{"type":["string","null"],"enum":["measured","not_measured","no_route","refused","unsellable","vendor_silent"],"description":"P90. What secondHopUsd MEANS. \"not_measured\": either the second hop was not searched (the first hop already cleared the floor; secondHopSkipped=true) OR it was searched and the counter assets' inventory and their own exit to USDC were measured, but the leg from THIS token into the counter asset was not — so secondHopUsd is inventory, not reach. \"no_route\": the factories were enumerated and list no other counter asset for this token. \"vendor_silent\": the enumeration could not be read (head block or factory logs unavailable). \"measured\" will only appear once the token→asset leg is quoted by us. When the pot clears the drain floor only through a not_measured second hop, the verdict is \"unknown\", never \"clear\" (see reasons). null = the liquidity axis produced no metrics at all."},"exitPotUnquotedUsd":{"type":["number","null"],"description":"P90. Dollars of counter asset sitting on venues whose quoter is NOT confirmed (the venue registry marks them `unquoted`). In the first hop that inventory is inside exitLiquidityUsd (it is real reserve in a direct pool); in the second hop it is NOT — the token→asset leg cannot be quoted there, so it is named here instead of being added. null = the liquidity axis produced no metrics at all."},"exitVenuesUnquoted":{"type":"array","items":{"type":"string"},"description":"The unquoted venues that held that inventory, by name."},"exitPotBasis":{"type":["string","null"],"enum":["position-sale","pool-inventory","second-hop"],"description":"P93. WHAT exitLiquidityUsd IS in this answer. \"position-sale\" = we quoted the sale of the very position this answer prices, and the pot is its proceeds. \"pool-inventory\" = that sale could not be quoted (no entry quote, or the node stayed silent), so the number is the counter asset sitting in the pools — what the pot meant before P93. \"second-hop\" = the number came from a counter-asset road measured by the second hop (the direct road paid less, or there is no direct dollar pool at all). Same field, three different facts: read it before comparing the pot to your size."},"exitReachUsd":{"type":["number","null"],"description":"P93. Dollars the sale of the position returns, quoted by our own engine on the direct road (no exotic road search — those are measured separately as secondHopUsd). The pot is the BEST road, never the sum."},"exitReachStatus":{"type":["string","null"],"enum":["measured","not_measured","no_route","refused","unsellable","vendor_silent"],"description":"P93. What exitReachUsd means: \"measured\" = the sale was quoted; \"no_route\" = the venues we cover offered no buyer at that size (a measurement, so the pot is a measured zero); \"vendor_silent\" = the node did not answer (we fall back to inventory and say so in exitPotBasis); \"not_measured\" = no entry quote existed, so there was no position to sell."},"exitReachRoad":{"type":["string","null"],"description":"P100. WHICH ROAD that sale took: \"direct\" when the position was sold straight into the dollar, or \"via <asset>\" naming the intermediate asset (its symbol when the asset is in our chain registry, its ADDRESS otherwise — we do not spend a node call on a label). Derived from the route already quoted, so it costs nothing and cannot disagree with the number. Read it against exitLadderScope: a pot measured \"via VIRTUAL\" next to exitLadderStatus: \"unsellable\" is not a contradiction — the two describe different roads. null = no sale was quoted (see exitReachStatus)."},"exitPoolInventoryUsd":{"type":["number","null"],"description":"P93. How many dollars of counter asset the direct pools HOLD. This is what exitLiquidityUsd used to be. It is an upper bound on any sale, not a promise: a deep pool can still pay little for YOUR size. P100 — TWO LIMITS ON READING IT AS AN UPPER BOUND. (1) When the v4 sale ladder ran, the v4 share of this number is the ladder's REACH and not inventory (the ladder replaces it), so for a token whose pools are all v4 the number is a FLOOR, not a ceiling. (2) It counts DIRECT first-hop pools only: if the sale travels token -> X -> dollar, the depth of the second leg is not in here at all. Measured 22.09.2026 on HOME (Base, block 51 611 500): exitPoolInventoryUsd $4 472.00 matched exitLadderTopUsd to the cent while selling the position returned $4 642.40 over a two-leg v4 road — the pot legitimately exceeded the \"upper bound\". Both roads are named: exitReachRoad for the sale, exitLadderScope for the ladder."},"asOfBlockFirst":{"type":["number","null"],"description":"Base block height when the liquidity axis STARTED reading. null = the block could not be read."},"asOfBlock":{"type":["number","null"],"description":"Base block height when it FINISHED. Equal to asOfBlockFirst means the whole axis was read inside one block and is reproducible there; different means no single block describes it, and the gap is the size of that uncertainty."}}}}},"example":{"chain":"base","identity":{"name":"Sogni AI","symbol":"SOGNI","decimals":18,"totalSupplyRaw":"9999052674620084038878069925","totalSupply":9999052674.620085,"note":"name, symbol, decimals and totalSupply read straight from the token contract at this block"},"valuation":{"fdvExecutableUsd":5669482.067795562,"basis":"totalSupply(this chain) x executablePrice(at sizeUSD)","note":"fully-diluted value at the price your size can actually execute at, not at spot. Two reasons it may differ from a market-data site: the executable price is worse than spot on thin books, and totalSupply is THIS chain's supply — for a bridged token the global figure is larger. The vendor's global figure travels in this same response as market.marketCapUsd: the two are DIFFERENT quantities, and a large gap between them is the bridged supply plus the spot-vs-executable spread, not a contradiction"},"ownership":{"ownerAddress":null,"ownerRenounced":null,"isMintable":true,"creatorAddress":"0x1550e91ca79b5492218162812efa8f989301e708","creatorBalance":0,"creatorSharePct":0,"note":"no owner()/getOwner() answered — ownership is unknown, which is NOT the same as renounced; a mint selector is present in the bytecode — supply can grow (presence of the function, not proof it is callable); creator inferred from the sender of the first transfer — a candidate, not a proven deployer"},"dormancy":{"topHolderIdleDays":0.0004166666666666667,"lastTopHolderMoveBlock":51728969,"headBlock":51728987,"note":"no top holder's balance has changed for 0.00 days (since block 51728969). Measured from real block timestamps. A long idle stretch means the large positions are not trading — read it with the same caution as concentration: pool and treasury CONTRACTS count as holders"},"market":{"priceUsdSpot":0.000561,"volume24hUsd":75517.39,"marketCapUsd":2018589,"holderCount":31524,"note":"third-party market data, republished as-is and signed as theirs in `sources` — we did not measure any of it. priceUsdSpot is DexScreener's SPOT print from the deepest Base pool for this token, NOT the price your order gets: that one is quote.executablePrice, it depends on sizeUSD, and on a thin book it is worse than spot. marketCapUsd is the vendor's GLOBAL figure — every chain, their supply source. Our valuation.fdvExecutableUsd is a DIFFERENT quantity: THIS chain's totalSupply times the price your size can execute at. For a bridged token ours is legitimately the smaller number, and the gap is the bridged supply plus the spot-vs-executable spread. Compare them, do not equate them. volume24hUsd sums DexScreener's 24h volume over the 1 Base pair(s) where this token is the BASE asset; pairs where it is the quote asset are not counted. holderCount is GoPlus's count of addresses on this chain — read it with the same caution as concentration: pool, bridge and treasury CONTRACTS are addresses too"},"sources":{"*":"measured","risk_profile.concentration":"vendor:graph","flags.F_CONC":"vendor:graph","valuation":"derived:identity.totalSupply*quote.executablePrice","dormancy":"derived:risk_profile.concentration.asOfBlock","ownership.creatorAddress":"derived:sender-of-first-transfer","ownership.isMintable":"derived:mint-selector-in-bytecode","market":"vendor:dexscreener+goplus","market.priceUsdSpot":"vendor:dexscreener","market.volume24hUsd":"vendor:dexscreener","market.marketCapUsd":"vendor:dexscreener","market.holderCount":"vendor:goplus"},"token":"0xE014d2A4da6E450f21b5050120D291e63c8940FD","verdict":"clear","triggers":[],"confidence":"low","reasons":["no provable trap detected. This is NOT a safety rating: it means none of the checks that can PROVE a trap (NO_EXIT_VENUE, EXIT_LIQUIDITY_DRAINED, TRADING_DISABLED) fired at this block, AND the liquidity sweep reached a conclusion (liquidityCoverage.conclusive). Structural risk — age, holder concentration, liquidity depth, transfer restrictions — is reported in risk_profile and can still be severe","hook-refused-quote — a Uniswap v4 pool whose hook has swap permissions rejected our quoter's simulation of the sale (a third-party quote), so that sale was not measured this call; no sale through that pool was observed in blocks 51426586–51728985, at most 7 days — see observedExit","not checked: independent price cross-check (a Chainlink feed, or a second venue pricing the same pair) — no Chainlink feed and no on-chain price on the 12 priced venue(s) of base. Reported as unknown, never as clean; confidence reduced accordingly","route-search-skipped:direct-exit-sufficient — the first hop already cleared the floor, so we did NOT enumerate exotic roads for this token: a better road may exist and was not looked for"],"risk_profile":{"age":{"ageDays":455.03,"genesisBlock":32071499,"note":"455.03 days since the first transfer — an established history, which says nothing about today's liquidity"},"concentration":{"top1SharePct":64.0204,"top10SharePct":88.0185,"holders":null,"holdersExact":false,"source":"graph","asOfBlock":51728969,"ageSec":null,"stale":false,"poolsExclusion":"applied","poolsExcluded":1,"poolsExcludedAddresses":["0xcc68cb8b514a2216d2eece3a0e8597ce483610eb"],"poolsSharePct":2.0678,"top1SharePctInclPools":64.0204,"top10SharePctInclPools":90.0863,"top10Bound":"lower","note":"top-1 holder holds 64.0204% of supply, top-10 hold 88.0185% (a FLOOR: the holder source lists a limited number of addresses and fewer than 10 non-pool holders remained in it). NOT counting 1 pool contract(s) holding 2.0678% of supply (addresses in poolsExcludedAddresses): what a pool holds is LIQUIDITY, not a position. With pools counted, as before: top-1 64.0204%, top-10 90.0863%. A single holder that large can move the price alone. Treasury, hook and bridge CONTRACTS still count as holders"},"liquidity":{"poolCount":8,"venueCount":1,"largestPoolSharePct":100,"exitLiquidityUsd":977.2,"exitPotBasis":"position-sale","exitPoolInventoryUsd":116037.32,"note":"8 pool(s) found across 1 venue(s). Selling the position this answer prices returns $977.2 — that is the pot, measured by quoting the sale, not the counter asset sitting in the pools (those pools hold $116037.32 of WETH/USDC/USDT, reported separately as exitPoolInventoryUsd)"},"oracle":{"source":null,"deviationBps":null,"stalenessSec":null,"note":"no independent price cross-check was available for this token. Outside the majors a Chainlink feed simply does not exist, so this is the normal case, not a warning sign"},"transferability":{"sellTaxRaw":null,"buyTaxRaw":null,"hasBlacklist":false,"hasMaxLimit":false,"tradingEnabled":null,"fingerprints":"none","note":"no tax, blacklist, limit or trading-gate function was found. Absence of these fingerprints is a negative result on a known list of patterns — not proof that the token is sellable"}},"quote":{"direction":"buy","tokenIn":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","tokenOut":"0xE014d2A4da6E450f21b5050120D291e63c8940FD","executablePrice":1763.6624571789096,"priceImpactBps":115.13464378379967,"depthAtSize":1763662.4571789096,"worstCaseSlippageBps":115.13464378379967,"confidence":"low"},"sizeUSD":"1000","disclaimer":"Informational economic-safety signal, not financial advice. verdict \"clear\" means NO PROVABLE TRAP was detected at this block AND the liquidity sweep reached a conclusion — it is not a safety rating and not a prediction; read risk_profile for structural risk. verdict \"avoid\" means a listed trap was conclusive. verdict \"unknown\" means the sweep did NOT reach a conclusion, so this call establishes neither a trap nor its absence — do not read it as \"clear\". Checks are heuristics over on-chain state and can miss novel traps.","ts":1790247323121,"validUntil":1790247326121,"coverage":{"axesExpected":5,"axesReporting":4},"liquidityCoverage":{"conclusive":true,"poolsFound":8,"factoriesChecked":13,"unmeasuredVenues":0,"unmeasuredVenueNames":[],"venuesUnread":0,"singletonPoolsSeen":31,"singletonPoolsCounted":7,"singletonPoolsRejected":22,"singletonPoolsHooked":1,"singletonScanTruncated":true,"asOfBlockFirst":51728985,"asOfBlock":51728987},"observedExit":{"basis":"v4-hook-refused-quote","status":"measured","windowFromBlock":51426586,"windowToBlock":51728985,"salesObserved":0,"lastSaleBlock":null,"largestSaleUsd":null,"medianDeviationPct":null,"salesCapped":false,"amountsBasis":"pool-leg-only","poolsRefused":1,"poolsNotRead":0,"pools":[{"poolId":"0x9d6f987fff7d484427ec6a99056dba5f0c44c3daa2de15ee8565a9b1ea941d09","hooks":"0x1Aa368e255A2856523FAD0b809dbfb90e5434088","hookFlags":["BEFORE_SWAP","BEFORE_SWAP_RETURNS_DELTA"],"counter":"0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2","status":"measured","salesObserved":0,"lastSaleBlock":null,"largestSaleUsd":null,"medianDeviationPct":null,"hookSwapsExcluded":0,"amountsBasis":"pool-leg-only"}]}}}}},"400":{"description":"Invalid input"},"402":{"description":"Payment required (x402 v2). The payment requirements (amount, USDC asset, payTo, accepted networks) are base64-JSON-encoded in the PAYMENT-REQUIRED response header. Sign an EIP-3009 USDC authorization (EVM networks) or submit a partially-signed SPL USDC transfer transaction (Solana) and retry the same request with the PAYMENT-SIGNATURE header (npm @x402/fetch automates this). The JSON body is an informative summary only — the header is authoritative.","headers":{"PAYMENT-REQUIRED":{"description":"base64(JSON) x402 v2 payment requirements: {x402Version, resource, accepts[]}","schema":{"type":"string"}}}},"422":{"description":"Chain not supported for pretrade — no on-chain-verified exit coverage for it. Served on: base, polygon, arbitrum. Per network — base (13 liquidity factories + uniswap-v4/pancakeswap-infinity, priced on uniswap-v3/aerodrome/aerodrome-cl-1/aerodrome-cl-2/aerodrome-cl-3/sushiswap-v3/uniswap-v2/sushiswap-v2/pancakeswap-v2/baseswap/alienbase/swapbased/uniswap-v4); polygon (15 liquidity factories + uniswap-v4, priced on uniswap-v3/sushiswap-v3/quickswap-v3/quickswap-v2/uniswap-v2/sushiswap-v2/apeswap/uniswap-v4); arbitrum (10 liquidity factories + uniswap-v4, priced on uniswap-v3/sushiswap-v3/ramses-v3/camelot-v3/sushiswap-v2/camelot-v2/uniswap-v2/uniswap-v4). The exit pot and the quote are measured on DIFFERENT venue lists by design: the pot only needs pool discovery and balances, a quote needs a quoter we have confirmed against the live market. Venues that count toward the exit pot but are NOT in the price: base — pancakeswap-v3, pancakeswap-infinity; polygon — retro, ramses-v3, w-dex, dooar, vulcandex, fraxswap, wault, polycat; arbitrum — pancakeswap-v3, ramses-v2, solidly-v3. On those the quote can be worse than the market while the safety verdict still sees that liquidity. A network that is not listed answers 422 — we do not publish a verdict where we have not measured the exit."},"429":{"description":"Rate limited"}}}},"/health":{"get":{"operationId":"health","summary":"Liveness (free)","responses":{"200":{"description":"ok"}}}}}}