Prerequisites: none. The scanner and both candle endpoints are public — no VOOI API token is required.
How results are shaped
GET /arbitrage-scanner returns { items, total }, where items is a page of coins and total counts every coin matching your filters. Each coin nests down two levels:
- Coin — one asset, keyed by
asset: the cross-venue alias key (alias:gold) when the asset is aliased, otherwise the base symbol shared across venues. This is the same key asunifiedSymbolonGET /exchange/markets. It also carriescategoryandexchangeCount. - Pair — one cross-exchange pairing of that coin, carrying the spreads.
- Leg — the
longandshortside of that pair, each a market on one venue with its own price, funding rate, open interest, 24h volume, and depth estimates.
Reading the signs
fundingSpread1h, priceSpread, and priceSpreadAtSize are signed and direction-specific, so a pair’s two directions carry roughly opposite values. The max… fields are not symmetric that way: each is a maximum taken over its own direction alone, so one direction’s value is not the negation of the other’s. Each leg keeps its own signed funding rate.
priceSpread and priceSpreadAtSize can disagree by more than depth alone. priceSpreadAtSize is recomputed from both legs’ fill prices at the notional you asked for, while priceSpread comes from a periodic snapshot. Treat priceSpreadAtSize as the one that reflects what you would actually get, and expect null when either leg has no estimate at that notional.Filtering and ranking
The scanner takesnotionalUsd (default 1000) — the size used to estimate each leg’s slippage and depth impact from the live order book — plus the usual exchanges filter.
Narrow the result set with categories (repeat the parameter for several; GET /exchange/markets/categories lists the values currently in use), symbol for one exact asset, query for a case-insensitive substring search over the asset key and leg symbols, excludeSymbols to drop base symbols, and the minFundingSpread, minPriceSpread, minOpenInterest, and minVolume thresholds. A coin survives a threshold when at least one of its pairs clears it.
Rank with orderBy (default fundingSpread1h) and orderDirection (default desc); each coin ranks by its best pair. Page with limit (1–100, default 15) and offset.
openInterest ranks by the thinner leg of the pair and volume24h by both legs combined, while the spread fields rank by the pair value itself. Aliases are not accepted in excludeSymbols — pass base symbols there.Charting one pair
Both candle endpoints take the same four parameters identifying the two legs:assetA / exchangeA and assetB / exchangeB. The asset parameters accept the same forms as asset elsewhere — see Markets, and prefer baseSymbol + quoteSymbol when you already have the row.
GET /arbitrage-scanner/funding-candles— per-minute funding rates for both legs over a window oflimitminutes ending atdateTo(defaults to now, never later than the current minute) shiftedoffsetminutes back. Page further into the past by increasingoffsetbylimit. Minutes with no recorded rate are omitted rather than zero-filled, so each leg carries between zero andlimitrates.GET /arbitrage-scanner/price-spread-candles— stored price-spread candles at aresolutionof1m,5m,15m,30m,1h,4h,12h, or1d, oldest first. Leg A is the buy (ask) side and leg B the sell (bid) side. Intervals without ticks are omitted, not zero-filled.
Next steps
Quotes and slippage
Price one leg precisely before committing
Markets
Asset categories and the alias /
unifiedSymbol key