Arbitrage history
curl --request GET \
--url https://api.probsights.com/v1/arbitrage/history \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.probsights.com/v1/arbitrage/history"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.probsights.com/v1/arbitrage/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"items": [
{}
],
"total": 123,
"offset": 123,
"limit": 123,
"has_more": true,
"first_seen_at": "<string>",
"last_seen_at": "<string>",
"opportunity": {},
"event_id": "<string>",
"event_title": "<string>",
"outcome_key": "<string>",
"label": "<string>",
"timestamp": "<string>",
"market_type": "<string>",
"interval_code": "<string>",
"resolution_time": "<string>",
"kalshi_event_ticker": "<string>",
"polymarket_event_slug": "<string>",
"kalshi": {},
"polymarket": {},
"buy_yes_market": "<string>",
"buy_no_market": "<string>",
"gross_cents": 123,
"fee_cents": 123,
"net_cents": 123,
"roi_percent": 123,
"executable_size": 123,
"max_profit_dollars": 123,
"yes_leg": {},
"no_leg": {},
"orderbook": {},
"locked": true
}Arbitrage
Arbitrage history
Paged historical arbitrage opportunities recorded by the background scanner.
GET
/
v1
/
arbitrage
/
history
Arbitrage history
curl --request GET \
--url https://api.probsights.com/v1/arbitrage/history \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.probsights.com/v1/arbitrage/history"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.probsights.com/v1/arbitrage/history', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"items": [
{}
],
"total": 123,
"offset": 123,
"limit": 123,
"has_more": true,
"first_seen_at": "<string>",
"last_seen_at": "<string>",
"opportunity": {},
"event_id": "<string>",
"event_title": "<string>",
"outcome_key": "<string>",
"label": "<string>",
"timestamp": "<string>",
"market_type": "<string>",
"interval_code": "<string>",
"resolution_time": "<string>",
"kalshi_event_ticker": "<string>",
"polymarket_event_slug": "<string>",
"kalshi": {},
"polymarket": {},
"buy_yes_market": "<string>",
"buy_no_market": "<string>",
"gross_cents": 123,
"fee_cents": 123,
"net_cents": 123,
"roi_percent": 123,
"executable_size": 123,
"max_profit_dollars": 123,
"yes_leg": {},
"no_leg": {},
"orderbook": {},
"locked": true
}Paged feed of every arbitrage opportunity episode recorded by the always-on
background scanner, newest first. Repeated detections of the same opportunity
extend an existing episode instead of creating a duplicate.
This is the endpoint the Dashboard arbitrage
table reads from, and the only place
Use
min_net_cents is applied server-side across
all recorded opportunities (not just the rows currently loaded in the UI).
Returns a page envelope: {items, total, offset, limit, has_more}.
Preview access (anonymous visitors, free accounts, unauthenticated API keys)
returns the first opportunity unmasked and locks the rest — see
Preview masking.
Request
https://api.probsights.com/v1/arbitrage/history
Query parameters
Minimum net profit after fees, in cents. Applied server-side over the full
history in the database, independent of the loaded page.
Response
Fieldsopinion_market_id and opinion are null for BTC interval scope and
omitted. All monetary fields are null for locked (preview) rows.
Episode
The detected opportunity object.
Opportunity
Polymarket leg snapshot:
condition_id, yes_token_id, no_token_id,
yes_ask, no_ask, volume, liquidity.Examples
15-minute opportunities with min edge
curl -H "X-API-Key: YOUR_API_KEY" \
"https://api.probsights.com/v1/arbitrage/history?min_net_cents=2&interval_code=15m&limit=20"
import requests
response = requests.get(
"https://api.probsights.com/v1/arbitrage/history",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"min_net_cents": 2, "interval_code": "15m", "limit": 20},
)
page = response.json()
const response = await fetch(
"https://api.probsights.com/v1/arbitrage/history?min_net_cents=2&interval_code=15m&limit=20",
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const page = await response.json();
Paginate through the feed
curl -H "X-API-Key: YOUR_API_KEY" \
"https://api.probsights.com/v1/arbitrage/history?limit=100&offset=100"
has_more to keep paging; total is the filtered count. Keep limit fixed
across pages for stable offset math.
Preview masking
Without a paid entitlement the scanner’s history is masked server-side: the opportunity shown first islocked: false with full prices and net_cents, and
every other row is locked: true with net_cents: null and both venue asks
removed. A Trader subscription — see Authentication —
unlocks the full feed.
Fee model
Arb legs are modeled as taker orders (buying at the ask):| Exchange | Formula (1 contract) | Rounding |
|---|---|---|
| Kalshi | 0.07 × price × (1 − price) | Round up to next cent |
| Polymarket (crypto) | 0.07 × price × (1 − price) | Round to 5 dp; min charge 0.00001 |