Skip to content

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.


GET/v1/arbitrage/cex-spot-transfer

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

GET
/v1/arbitrage/cex-spot-transfer
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:

indicativeReasonMeaning
below_feesThe route does not clear its fees (netProfitPct at or below zero).
stale_quoteAn order book is older than 60 seconds.
stale_networkA 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.

Was this page helpful?