Pools
Uniswap v4 pools on Ethereum (1), Arbitrum One (42161) and Avalanche (43114), ranked by TVL, 24h volume, 24h fees, fee APR or age.
GET /v1/pools — 2 units
curl -s "https://api.tickwise.xyz/v1/pools?chainId=1&sort=tvl&limit=25" \
-H "KC-APIKey: $TICKWISE_API_KEY"Query parameters
| Parameter | Default | Meaning |
|---|---|---|
| chainId | all chains | 1 or 43114. Omitting it merges every enabled chain into one ranking. |
| protocol | uniswap-v4 | The only value served; anything else is a 400. |
| sort | tvl | tvl, volume, fees, fee_apr or age. Descending except age, which is oldest first. There is no direction parameter. |
| page | 1 | 1-based. |
| limit | 20 | 1–100. |
| minTvlUsd | 0 | Floor on pool TVL. |
| includeRisky | false | Admits pools whose tokens have no corroborated on-chain market. |
| search | — | Case-insensitive substring over either token symbol, either token address, or the pool id. Up to 64 characters. It is a lookup, not a filter: the spam-token exclusion is skipped while searching, so a pool you name stays findable. |
Response
A pools array and the same pagination envelope the positions list uses. Each row carries rank, poolId, chainId, protocol, both token snapshots, fee, isDynamicFee, tickSpacing, currentTick, sqrtPriceX96, liquidity, createdAtTimestamp, a metrics group (tvlUsd, volumeUsd24h, volumeUsd7d, feesUsd24h, feesUsd7d, feeApr, txCount, currentPrice), pricing, and two counts the underlying subgraph does not provide: positionsCount (open positions) and holdersCount (distinct owners). The same rules apply to total here: it is a floor when totalCapped is true, so page with hasMore.
The two counts are computed separately from the pool rows. For a very large pool they can still be in progress when the response is built. Those pools then carry null for both counts, and the list response adds "countsPending": true. Read null as “not known yet”, not as zero. A later request returns the numbers.
Two more flags, each present only when it applies. In all-chains mode (no chainId), a chain whose data is temporarily unavailable is left out rather than failing the whole request: the response adds "partial": true and "missingChains": […], the rows are the other chains’ merged order, total counts only those chains, and the request is not charged. Data older than the usual 45-second freshness is only ever served flagged: it carries "stale": true and dataAsOf, the time it was current. That happens when the database is too slow to answer (the last page we served comes back instead), when the database replica it was read from is running behind, and on a very deep page whose position in the list was counted more than 45 seconds ago. There is no page cap. Paging forward from one page to the next is cheap; the first visit to a very deep page can answer 503 with Retry-After while it is still being reached, and the retry continues from where that request got to.
feeApr is clamped at ±100,000% on the way out. The upstream v4 subgraph’s feesUSD is known to produce values in the hundreds of thousands of percent on thin pools; clamping at read time keeps a stale document from dominating a fee_apr ranking. A value sitting exactly on the cap should be read as “not trustworthy”, not as a measurement.
GET /v1/pools/{chainId}/{protocol}/{poolId} — 1 unit
One pool, in the same shape as a list row plus its counts. poolId is validated before anything else happens: a v4 pool id is 0x plus 64 hex characters, a v3 pool address 0x plus 40. Anything else is a 400 with {"error":"Invalid poolId"}, rejected here rather than fanned out to a metered upstream.
curl -s "https://api.tickwise.xyz/v1/pools/1/uniswap-v4/0x…64hex" \
-H "KC-APIKey: $TICKWISE_API_KEY"Ids are matched lowercased, so case in the path does not matter. A pool that exists on the other chain is a 404 here.
Like the list, a pool older than the 45-second freshness — its holder counts kept past their freshness, a database replica running behind, or the last copy served because the database was too slow — carries "stale": true and dataAsOf, the time it was current.
GET /v1/pools/{chainId}/{protocol}/{poolId}/charts — 10 units
?range=30d|60d|90d|180d|all, defaulting to 30d; an unrecognised value falls back to 30d rather than erroring.
curl -s "https://api.tickwise.xyz/v1/pools/1/uniswap-v4/0x…64hex/charts?range=90d" \
-H "KC-APIKey: $TICKWISE_API_KEY"Carries poolPrice (daily OHLC), poolOverview, liquidityDistribution (the tick histogram, with no position range marked — that is the difference from the position variant), poolSeries (volume, TVL, fees, fee APR) and poolOverviewCurrent, which is null when the pool has no day data.
As on positions, poolOverview.divergence is always empty: the upstream schema does not carry it, and the key exists so it can be filled later without breaking clients. This route is the expensive one — see units and limits.