CEX Spot Transfer Arbitrage
Buy a coin on one exchange, withdraw it, deposit it on another and sell it there. The scanner prices each route from live order books after exact network matching, token-contract matching, withdrawal/deposit status and minimums, withdrawal fees, each venue's taker fee, depth and slippage. Routes that clear every cost come first; the closest near misses follow so an empty board still shows how far off the best routes are.
List CEX spot-transfer rows
Supported transfer venues are KuCoin, Bitget, HTX, and CoinEx (public order books and public transfer metadata). A venue whose bulk ticker shows no live USDT market is left out of the scan and counted not_live (CoinEx since its halt); it rejoins by itself once it trades again. Other exchanges are excluded until authenticated wallet metadata for transfer fees and deposit/withdraw status is configured.
A route needs one common network where the buy venue can withdraw and the sell venue can deposit. Networks pair on one exact key per chain: an ambiguous network name (plain AVAX could be X-Chain or C-Chain) or a key a venue lists twice is refused. When either venue reports a token contract, both must report the same address; same-ticker contract mismatches fail closed. A percentage withdrawal fee, or an amount below the network's minimum withdrawal or deposit, refuses the route.
Order: executable routes first, then the indicative rest, each by netProfitPct, highest first. Every route netting above zero is served; after them come up to 50 near-miss routes (netProfitPct at or below zero) as indicative with indicativeReason: below_fees. meta.transferScan counts what the scan evaluated.
Freshness: one quote SLA of 60 seconds (the answer's freshness_sla_seconds); transfer networks are judged on 10 minutes and coin catalogs on 1 hour. A selected venue that answers no book, no network or no catalog makes the answer degraded (never cached, X-Data-Partial names it).
When coin is omitted, the scan covers the top 40 USDT spot coins with a live book on at least two supported venues, ranked by the thinner venue's 24h volume. Use coin to force-check one symbol.
Query parameters
- Name
coin- Type
- string
- Description
- Optional base coin.
- Name
exchanges- Type
- string
- Description
- Comma-separated exchange filter: KuCoin, Bitget, HTX, CoinEx.
- Name
minApr- Type
- number
- Description
- Minimum
netProfitPct(per trip, not annualized) in percentage points.
- Name
minDepthUsd- Type
- number
- Description
- Minimum visible order-book depth in USD.
- Name
notional- Type
- number
- Description
- Position notional in USD. Defaults to 10000. Order-book fills are sized to it.
- Name
limit- Type
- integer
- Description
- Rows per page. Defaults to 100.
- Name
cursor- Type
- string
- Description
- Opaque cursor from the previous page.
Request
curl -G https://www.sharpe.ai/api/v1/arbitrage/cex-spot-transfer \
-H "Authorization: Bearer sk_live_your_key_here" \
--data-urlencode "coin=SUI" \
--data-urlencode "notional=10000"
Response
{
"data": {
"rows": [
{
"rank": 1,
"coin": "SUI",
"buyExchange": "KuCoin",
"sellExchange": "HTX",
"buyAsk": 3.215,
"sellBid": 3.221,
"grossSpreadPct": 0.186625,
"network": "SUI",
"contractAddress": null,
"withdrawFee": 0.1,
"depositStatus": "Open",
"withdrawStatus": "Open",
"transferEta": "30 confs",
"transferConfirmations": 30,
"depthUsd": 41200,
"slippagePct": 0,
"netProfitPct": -0.117,
"buyTakerFeePct": 0.1,
"sellTakerFeePct": 0.2,
"spreadLifetimeSeconds": 45,
"updatedAt": "2026-09-30T08:00:02.000Z",
"networkUpdatedAt": "2026-09-30T07:57:10.000Z",
"isStale": false,
"executionStatus": "indicative",
"indicativeReason": "below_fees"
}
],
"scannerMeta": {
"kind": "cex-spot-transfer",
"status": "ok",
"source": "live",
"freshnessSlaSeconds": 60,
"notionalUsd": 10000,
"rowCount": 1,
"supportedCoins": ["SUI"],
"transferScan": {
"coinsScanned": 1,
"scannedCoins": ["SUI"],
"venuesAnswering": 3,
"venues": [
{ "exchange": "KuCoin", "status": "ok" },
{ "exchange": "Bitget", "status": "ok" },
{ "exchange": "HTX", "status": "ok" },
{ "exchange": "CoinEx", "status": "not_live" }
],
"routesEvaluated": 6,
"routesProfitable": 0,
"bestNetPct": -0.117
}
},
"pagination": { "cursor": null, "has_more": false, "total": 1 }
},
"meta": {
"request_id": "req_abc123def456ghij",
"timestamp": "2026-09-30T08:00:04.000Z",
"elapsed_ms": 1840
}
}
Formula
netProfitPct = [VWAP_sell(q − withdrawFee) × (1 − sellTakerFee) − N × (1 + buyTakerFee)] / N × 100
N is the notional, q the base amount the notional buys on the buy venue's asks, withdrawFee the buy venue's fixed withdrawal fee in coin units, and VWAP_sell the sell venue's bid fill for what arrives. buyTakerFeePct and sellTakerFeePct are each venue's spot taker fee: the venue catalog's own where it reports one (KuCoin, Bitget, CoinEx), else the shared venue fee table (HTX 0.2%). grossSpreadPct = (sellBid / buyAsk − 1) × 100 before any cost. netProfitPct is per trip, not annualized.
A route is executable when both order books are at most 60 seconds old, both transfer-network reads are at most 10 minutes old, both books fill the notional, and the net is above zero. Otherwise it is indicative:
indicativeReason | Meaning |
|---|---|
below_fees | The route does not clear its fees (netProfitPct at or below zero). |
stale_quote | An order book is older than 60 seconds. |
stale_network | A transfer-network read is older than 10 minutes. |
transferConfirmations is the number of deposit confirmations the sell venue waits for on the route's network (the wait before the coins can be sold); transferEta is the same count as a label, kept as a deprecated alias. updatedAt is the older of the two order books, networkUpdatedAt the older of the two network reads. spreadLifetimeSeconds is how long this server instance has seen the route: it resets on a cold start and differs between instances.