Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Arbitron App Spreads API
version: 1.0.0
contact:
name: Arbitron
url: https://arbitron.app/developers
email: support@arbitron.app
termsOfService: https://arbitron.app/terms
description: 'Operations tagged Spreads across 2 of this provider''s published API definitions: arbitron-openapi.json, arbitron-app-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://arbitron.app
description: Production
security:
- ApiKey: []
tags:
- name: Spreads
description: 'Cross-venue spreads on the same coin: the live print from the spread engine, and the scanner''s backtest priced against order-book depth.'
paths:
/api/v1/spreads:
get:
tags:
- Spreads
summary: Current cross-venue spreads
description: 'The spread between two venues'' perpetuals on the same coin right now, one row per venue pair and symbol, from the engine''s last print (seconds old). `spread_pct` is the better of the two entry directions and `direction` says which; both are given, with the bid and ask on each leg.
On the Demo plan the print arrives 15 minutes late, and the five widest spreads of every venue (on either leg) are withheld whatever the filter. `meta.withheld` is the number withheld from the whole snapshot, the same whatever the filter, and the cursor stops after 100 rows.
For how often a spread paid over a window, use `/spreads/backtest`.'
operationId: listSpreads
parameters:
- name: coin
in: query
description: One ticker or a comma-separated list, e.g. `BTC,ETH`. Case-insensitive.
schema:
type: string
- name: exchange
in: query
description: Keep pairs with these venues. One venue or a comma-separated list, spelled as `/exchanges` spells it, e.g. `Binance,Bybit`.
schema:
type: string
- name: exchange_match
in: query
description: '`any` (default): either leg is in `exchange`. `all`: both legs are, i.e. spreads among the listed venues only.'
schema:
type: string
- name: exclude_exchange
in: query
description: Drop pairs with any of these venues on either leg. One venue or a comma-separated list, spelled as `/exchanges` spells it, e.g. `Binance,Bybit`.
schema:
type: string
- name: min_spread_pct
in: query
description: Keep pairs whose `spread_pct` is at least this many percent, e.g. `0.3`.
schema:
type: number
format: double
- name: max_spread_pct
in: query
description: Keep pairs whose `spread_pct` is at most this many percent, e.g. `5` to drop dead markets.
schema:
type: number
format: double
- name: direction
in: query
description: '`long_a_short_b` or `short_a_long_b`: keep pairs whose better side is that one. Default: both.'
schema:
type: string
- name: min_volume_usdt
in: query
description: Keep pairs where BOTH legs' 24h volume is at least this many USDT, e.g. `500000`.
schema:
type: number
format: double
- name: min_strength
in: query
description: Keep pairs whose `strength` is at least this, 0 to 5.
schema:
type: integer
format: int32
- name: max_age_seconds
in: query
description: Keep pairs printed within this many seconds of `meta.as_of`, 1 to 120.
schema:
type: integer
format: int32
- name: sort
in: query
description: '`spread_desc` (default), `spread_asc`, `volume_desc`, `volume_asc`, `strength_desc`, `updated_desc`, `coin_asc`. Volume is the smaller leg''s.'
schema:
type: string
- name: limit
in: query
description: 'Rows per page, 1 to 500 (Demo: 50). Default 100.'
schema:
type: integer
format: int32
- name: cursor
in: query
description: '`meta.next_cursor` from the previous page.'
schema:
type: string
- name: fields
in: query
description: Comma-separated row fields to keep, e.g. `exchange,coin,rate_pct`; the others are dropped from every row. Unknown names are a 400 that lists the fields.
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ApiEnvelopeOfIReadOnlyListOfCurrentSpreadItem'
example:
data:
- symbol: SOL-USDT
coin: SOL
exchange_a: Binance
exchange_b: Bybit
spread_pct: 0.4132
direction: short_a_long_b
long_a_short_b_pct: -0.521
short_a_long_b_pct: 0.4132
bid_a: 142.31
ask_a: 142.32
bid_b: 141.72
ask_b: 141.73
volume_a_usdt: 512000000
volume_b_usdt: 388000000
funding_rate_a_pct: 0.01
funding_rate_b_pct: 0.0056
funding_interval_hours_a: 8
funding_interval_hours_b: 8
next_funding_at_a: '2026-09-21T16:00:00Z'
next_funding_at_b: '2026-09-21T16:00:00Z'
strength: 3
updated_at: '2026-09-21T12:00:01Z'
meta:
as_of: '2026-09-21T12:00:04Z'
delayed_seconds: 0
source: arbitron.app
url: https://arbitron.app/signals?utm_source=api
count: 1
total: 2493
next_cursor: MQ
'400':
description: Bad Request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ApiProblem'
example:
type: https://arbitron.app/developers/errors#invalid-parameter
title: A parameter is not valid
status: 400
detail: '''sort'' must be one of abs_rate_desc, abs_rate_asc, rate_desc, rate_asc, apr_desc, apr_asc, sum_7d_desc, sum_7d_asc, sum_30d_desc, sum_30d_asc, volume_desc, volume_asc, next_funding_asc, next_funding_desc, coin_asc, exchange_asc.'
instance: 0HN7Q2K3J4L5M:00000001
code: invalid-parameter
docs: https://arbitron.app/developers/errors
servers:
- url: https://arbitron.app
description: Production
/api/v1/spreads/backtest:
get:
tags:
- Spreads
summary: Backtested cross-venue spreads
description: 'The public scanner''s ranked spreads, priced against real order-book depth for an order of `size_usd` over the scan window. `est_profit_pct` is per round trip after fees; `cycles` counts how often the spread opened and closed. `strategy_url` opens a new strategy on the pair in the terminal, coin and both venues filled in.
A backtest, not the live print: use `/spreads` for what the spread is right now. The Demo plan withholds the five best rows of every venue (on either leg) whatever the filter. `withheld_top` is the number withheld from the whole snapshot, the same whatever the filter, and the cursor stops after 100 rows. Paid plans see every row.'
operationId: listSpreadBacktest
parameters:
- name: size_usd
in: query
description: 'Order size the depth is priced at: `25`, `100` or `500`. Default `100`.'
schema:
type: integer
format: int32
- name: coin
in: query
description: One ticker or a comma-separated list, e.g. `BTC,ETH`. Case-insensitive.
schema:
type: string
- name: exchange
in: query
description: Keep spreads with these venues. One venue or a comma-separated list, spelled as `/exchanges` spells it, e.g. `Binance,Bybit`.
schema:
type: string
- name: exchange_match
in: query
description: '`any` (default): either leg is in `exchange`. `all`: both legs are.'
schema:
type: string
- name: exclude_exchange
in: query
description: Drop spreads with any of these venues on either leg. One venue or a comma-separated list, spelled as `/exchanges` spells it, e.g. `Binance,Bybit`.
schema:
type: string
- name: min_profit_pct
in: query
description: Keep spreads whose `est_profit_pct` is at least this.
schema:
type: number
format: double
- name: max_profit_pct
in: query
description: Keep spreads whose `est_profit_pct` is at most this.
schema:
type: number
format: double
- name: min_avg_profit_pct
in: query
description: Keep spreads whose `avg_profit_pct` is at least this.
schema:
type: number
format: double
- name: min_cycles
in: query
description: Keep spreads that opened and closed at least this many times over the window.
schema:
type: integer
format: int32
- name: min_confidence
in: query
description: Keep spreads whose `confidence` is at least this, 0 to 100.
schema:
type: integer
format: int32
- name: min_volume_usdt
in: query
description: Keep spreads where BOTH legs' 24h volume is at least this many USDT.
schema:
type: number
format: double
- name: active_within_hours
in: query
description: Keep spreads whose last cycle closed within this many hours, 1 to 720.
schema:
type: integer
format: int32
- name: sort
in: query
description: '`profit_desc` (default), `profit_asc`, `avg_profit_desc`, `cycles_desc`, `confidence_desc`, `volume_desc`, `spread_range_desc`, `last_cycle_desc`, `coin_asc`.'
schema:
type: string
- name: limit
in: query
description: 'Rows per page, 1 to 500 (Demo: 50). Default 100.'
schema:
type: integer
format: int32
- name: cursor
in: query
description: '`meta.next_cursor` from the previous page.'
schema:
type: string
- name: fields
in: query
description: Comma-separated row fields to keep, e.g. `exchange,coin,rate_pct`; the others are dropped from every row. Unknown names are a 400 that lists the fields.
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ApiEnvelopeOfSpreadBacktestResponse'
example:
data:
size_usd: 100
withheld_top: 0
spreads:
- symbol: ENA-USDT
coin: ENA
exchange_a: BingX
exchange_b: Lighter
est_profit_pct: 3.9783
avg_profit_pct: 1.214
fee_pct_cycle: 0.14
spread_range_pct: 6.2
cycles: 75
confidence: 69
volume_a_usdt: 21000000
volume_b_usdt: 9800000
last_cycle_at: '2026-09-21T11:41:00Z'
strategy_url: https://arbitron.app/dashboard?symbol=ENA-USDT&exA=BingX&exB=Lighter&utm_source=api
meta:
as_of: '2026-09-21T12:00:04Z'
delayed_seconds: 0
source: arbitron.app
url: https://arbitron.app/arbitrage-scanner?utm_source=api
count: 1
total: 58
next_cursor: MQ
'400':
description: Bad Request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ApiProblem'
example:
type: https://arbitron.app/developers/errors#invalid-parameter
title: A parameter is not valid
status: 400
detail: '''sort'' must be one of abs_rate_desc, abs_rate_asc, rate_desc, rate_asc, apr_desc, apr_asc, sum_7d_desc, sum_7d_asc, sum_30d_desc, sum_30d_asc, volume_desc, volume_asc, next_funding_asc, next_funding_desc, coin_asc, exchange_asc.'
instance: 0HN7Q2K3J4L5M:00000001
code: invalid-parameter
docs: https://arbitron.app/developers/errors
servers:
- url: https://arbitron.app
description: Production
components:
schemas:
ApiProblem:
required:
- type
- title
- status
- detail
- instance
- code
- docs
type: object
properties:
type:
type: string
title:
type: string
status:
type: integer
format: int32
detail:
type: string
instance:
type: string
code:
type: string
docs:
type: string
suggestions:
type:
- 'null'
- array
items:
type: string
CurrentSpreadItem:
required:
- symbol
- coin
- exchange_a
- exchange_b
- spread_pct
- direction
- long_a_short_b_pct
- short_a_long_b_pct
- bid_a
- ask_a
- bid_b
- ask_b
- volume_a_usdt
- volume_b_usdt
- funding_rate_a_pct
- funding_rate_b_pct
- funding_interval_hours_a
- funding_interval_hours_b
- next_funding_at_a
- next_funding_at_b
- strength
- updated_at
type: object
properties:
symbol:
type: string
coin:
type: string
exchange_a:
type: string
exchange_b:
type: string
spread_pct:
type: number
format: double
direction:
type: string
long_a_short_b_pct:
type: number
format: double
short_a_long_b_pct:
type: number
format: double
bid_a:
type: number
format: double
ask_a:
type: number
format: double
bid_b:
type: number
format: double
ask_b:
type: number
format: double
volume_a_usdt:
type: number
format: double
volume_b_usdt:
type: number
format: double
funding_rate_a_pct:
type:
- 'null'
- number
format: double
funding_rate_b_pct:
type:
- 'null'
- number
format: double
funding_interval_hours_a:
type:
- 'null'
- integer
format: int32
funding_interval_hours_b:
type:
- 'null'
- integer
format: int32
next_funding_at_a:
type:
- 'null'
- string
format: date-time
next_funding_at_b:
type:
- 'null'
- string
format: date-time
strength:
type: integer
format: int32
updated_at:
type: string
format: date-time
ApiEnvelopeOfIReadOnlyListOfCurrentSpreadItem:
required:
- data
- meta
type: object
properties:
data:
type:
- 'null'
- array
items:
$ref: '#/components/schemas/CurrentSpreadItem'
meta:
$ref: '#/components/schemas/ApiMeta'
ApiMeta:
required:
- as_of
- delayed_seconds
- source
- url
type: object
properties:
as_of:
type: string
format: date-time
delayed_seconds:
type: integer
format: int32
source:
type: string
url:
type: string
count:
type:
- 'null'
- integer
format: int32
total:
type:
- 'null'
- integer
format: int32
next_cursor:
type:
- 'null'
- string
withheld:
type:
- 'null'
- integer
format: int32
ApiEnvelopeOfSpreadBacktestResponse:
required:
- data
- meta
type: object
properties:
data:
oneOf:
- type: 'null'
- $ref: '#/components/schemas/SpreadBacktestResponse'
meta:
$ref: '#/components/schemas/ApiMeta'
SpreadBacktestItem:
required:
- symbol
- coin
- exchange_a
- exchange_b
- est_profit_pct
- avg_profit_pct
- fee_pct_cycle
- spread_range_pct
- cycles
- confidence
- volume_a_usdt
- volume_b_usdt
- last_cycle_at
type: object
properties:
symbol:
type: string
coin:
type: string
exchange_a:
type: string
exchange_b:
type: string
est_profit_pct:
type: number
format: double
avg_profit_pct:
type: number
format: double
fee_pct_cycle:
type: number
format: double
spread_range_pct:
type: number
format: double
cycles:
type: integer
format: int32
confidence:
type: integer
format: int32
volume_a_usdt:
type: number
format: double
volume_b_usdt:
type: number
format: double
last_cycle_at:
type:
- 'null'
- string
format: date-time
strategy_url:
type:
- 'null'
- string
SpreadBacktestResponse:
required:
- size_usd
- withheld_top
- spreads
type: object
properties:
size_usd:
type: integer
format: int32
withheld_top:
type: integer
format: int32
spreads:
type: array
items:
$ref: '#/components/schemas/SpreadBacktestItem'
securitySchemes:
ApiKey:
type: http
description: Your API key as a bearer token. The X-Api-Key header is accepted too.
scheme: bearer
bearerFormat: arb_live_<43 chars>_<6 chars>
x-refined-from:
- arbitron-openapi.json
- arbitron-app-openapi.json