curl --request GET \
--url https://perps-api.vooi.io/arbitrage-scannerimport requests
url = "https://perps-api.vooi.io/arbitrage-scanner"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://perps-api.vooi.io/arbitrage-scanner', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://perps-api.vooi.io/arbitrage-scanner",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://perps-api.vooi.io/arbitrage-scanner"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://perps-api.vooi.io/arbitrage-scanner")
.asString();require 'uri'
require 'net/http'
url = URI("https://perps-api.vooi.io/arbitrage-scanner")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"items": [
{
"asset": "alias:gold",
"category": "commodities",
"exchangeCount": 4,
"pairs": [
{
"fundingSpread1h": "0.0000215",
"long": {
"baseSymbol": "BTC",
"bestAsk": "65001.0",
"bestBid": "65000.0",
"depthImpact": 0.08,
"exchange": "aster",
"fundingRate": "0.0000125",
"marketId": "BTCUSDT",
"maxLeverage": 20,
"nextFundingTime": "2026-07-17T12:00:00.000Z",
"openInterest": "12345678.9",
"price": "65000.5",
"price24hPercent": -1.23,
"quoteSymbol": "USDT",
"slippage": 0.12,
"volume24h": 3400000
},
"maxFundingSpread1h": "0.0000318",
"maxFundingSpread24h": "0.0000512",
"maxPriceSpread1h": "0.0231",
"maxPriceSpread24h": "0.0417",
"priceSpread": "0.0184",
"priceSpreadAtSize": "0.0121",
"short": {
"baseSymbol": "BTC",
"bestAsk": "65001.0",
"bestBid": "65000.0",
"depthImpact": 0.08,
"exchange": "aster",
"fundingRate": "0.0000125",
"marketId": "BTCUSDT",
"maxLeverage": 20,
"nextFundingTime": "2026-07-17T12:00:00.000Z",
"openInterest": "12345678.9",
"price": "65000.5",
"price24hPercent": -1.23,
"quoteSymbol": "USDT",
"slippage": 0.12,
"volume24h": 3400000
}
}
]
}
],
"total": 0
}List arbitrage scanner opportunities
Returns cross-exchange funding-arbitrage opportunities grouped by coin. Each market pair appears in both trade directions. fundingSpread1h, priceSpread and priceSpreadAtSize are signed and direction-specific, so the two directions of a pair carry roughly opposite values; the maxFundingSpread and maxPriceSpread fields are each a maximum taken over that direction alone, so one direction value is not the negation of the other. Each leg keeps its own signed funding rate. Prices, funding rates and open interest are current live values. Each coin carries the category of its underlying; GET /exchange/markets/categories lists the categories available to filter by.
curl --request GET \
--url https://perps-api.vooi.io/arbitrage-scannerimport requests
url = "https://perps-api.vooi.io/arbitrage-scanner"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://perps-api.vooi.io/arbitrage-scanner', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://perps-api.vooi.io/arbitrage-scanner",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://perps-api.vooi.io/arbitrage-scanner"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://perps-api.vooi.io/arbitrage-scanner")
.asString();require 'uri'
require 'net/http'
url = URI("https://perps-api.vooi.io/arbitrage-scanner")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"items": [
{
"asset": "alias:gold",
"category": "commodities",
"exchangeCount": 4,
"pairs": [
{
"fundingSpread1h": "0.0000215",
"long": {
"baseSymbol": "BTC",
"bestAsk": "65001.0",
"bestBid": "65000.0",
"depthImpact": 0.08,
"exchange": "aster",
"fundingRate": "0.0000125",
"marketId": "BTCUSDT",
"maxLeverage": 20,
"nextFundingTime": "2026-07-17T12:00:00.000Z",
"openInterest": "12345678.9",
"price": "65000.5",
"price24hPercent": -1.23,
"quoteSymbol": "USDT",
"slippage": 0.12,
"volume24h": 3400000
},
"maxFundingSpread1h": "0.0000318",
"maxFundingSpread24h": "0.0000512",
"maxPriceSpread1h": "0.0231",
"maxPriceSpread24h": "0.0417",
"priceSpread": "0.0184",
"priceSpreadAtSize": "0.0121",
"short": {
"baseSymbol": "BTC",
"bestAsk": "65001.0",
"bestBid": "65000.0",
"depthImpact": 0.08,
"exchange": "aster",
"fundingRate": "0.0000125",
"marketId": "BTCUSDT",
"maxLeverage": 20,
"nextFundingTime": "2026-07-17T12:00:00.000Z",
"openInterest": "12345678.9",
"price": "65000.5",
"price24hPercent": -1.23,
"quoteSymbol": "USDT",
"slippage": 0.12,
"volume24h": 3400000
}
}
]
}
],
"total": 0
}Query Parameters
Supported perpetual exchange
aster, binance, bybit, extended, gate, hyperliquid, lighter, mexc, ondo, robinhood Keep only coins whose asset class is one of these (repeat the query param to pass several); omit to keep every category. A coin has a single category because both legs are the same underlying. Asset class of the market
commodities, crypto, etf-index, forex, pre-ipo, stocks-asia, stocks-us Exclude these base symbols from the results (repeat the query param to pass several); a pair is dropped when at least one of its legs matches. Alias keys are not accepted. Asset identifier: base symbol (e.g. "ETH") or full pair (e.g. "ETHUSDC").
1"ETH"
Number of coins to return per page (1–100).
1 <= x <= 100Keep only coins with at least one pair whose hourly funding spread is at least this decimal fraction.
\d+(\.\d+)?"0.001"
Keep only coins with at least one pair whose thinner leg has open interest of at least this USD notional (one-sided).
x >= 0Keep only coins with at least one pair whose price spread is at least this decimal fraction.
\d+(\.\d+)?"0.001"
Keep only coins with at least one pair whose combined 24h volume in USD is at least this value.
\d+(\.\d+)?"0.001"
Notional in USD used to estimate per-leg slippage from the live order book.
Number of coins to skip.
0 <= x <= 9007199254740991Pair-level numeric field to rank coins by; each coin ranks by its best pair. openInterest ranks by the thinner leg of the pair and volume24h by both legs combined; the spread fields rank by the pair value itself.
fundingSpread1h, maxFundingSpread1h, maxFundingSpread24h, maxPriceSpread1h, maxPriceSpread24h, openInterest, priceSpread, volume24h Sort direction over the ranked coins.
asc, desc Case-insensitive substring search over the coin asset key (alias keys match by their name without the alias: prefix) and each leg's symbols.
1Return only the coin with this exact case-insensitive alias (if exists for market) or base symbol; combine with two exchanges to fetch a single cross-market pair in both trade directions.