Public REST API
Programmatic access to Polymarket whale analytics, ISW territory data, and leaderboards. Available on Premium ($19.99/mo).
Client libraries & tools
Official clients wrap this API โ or call the plain REST endpoints below from any language.
- Python SDK โ
pip install orcalayerยท github.com/orcalayer/orcalayer-python - MCP server (AI agents) โ
uvx orcalayer-mcpยท orcalayer-mcp - Agent skill (Claude Code / Desktop) โ orcalayer-skill
- Whale watchlist monitor โ whale-watchlist-monitor
- Backtest cookbook โ polymarket-backtest-cookbook
- OpenAPI spec โ /api/openapi.json
Quickstart
- Sign up and upgrade to Premium
- Go to Settings โ API Keys and click Generate Key
- Copy the key (format
sk_orca_XXXXXX) โ it's shown only once - Make authenticated requests:
curl -H "Authorization: Bearer sk_orca_XXXXXX" \
"https://orcalayer.com/api/public/v1/whales/leaderboard?limit=10"Authentication
For /api/public/v1/* endpoints, send your API key either as a Bearer token in the Authorization header or as an x-api-key header โ both work. Premium endpoints under /api/v2/* (whale-alerts, whales/recent-trades, whale-flips, wallet trades, market whale-trades) require the x-api-key header specifically. Public read endpoints (wallet profiles, market search, leaderboard) need no key.
# /api/public/v1/* โ either header works:
Authorization: Bearer sk_orca_XXXXXX
x-api-key: sk_orca_XXXXXX
# premium /api/v2/* โ use x-api-key:
x-api-key: sk_orca_XXXXXX- Missing key โ
401 Unauthorized - Revoked / invalid key โ
401 - Valid key but plan โ premium โ
403 Forbidden - Rate limit exceeded โ
429 Too Many RequestswithRetry-After: 60
Wins / Losses / Win Rate / Profit Factor โ data semantics
As of 2026-05-06, wins, losses, win_rate, and profit_factor are computed from Polymarket data-api.polymarket.com/closed-positions data when our cache is complete (โฅ95% of expected closed positions, measured via Polymarket data-api.polymarket.com/traded API).
- Cache complete โ matches Polymarket UI counters (most wallets).
- Cache truncated (top whales with 1M+ trade events) โ falls back to a per-market resolved metric (1 unit per market; NegRisk multi-market events counted once) for these high-volume wallets.
profit_factoruses the cache PnL ratio (looser guard โ ratios stable even when cache truncated). Capped at 99.99x; real may be higher with rare losses.total_pnlalways uses Polymarket's lifetime PnL (from their leaderboard API) when synced โ the authoritative source.
Contract addresses (not user wallets)
Polymarket router/exchange contract addresses are excluded from wallet endpoints (they aggregate ALL trades through the router, not a single user). Querying these returns an explicit error response shape rather than fake whale stats:
{
"error": "This address is a Polymarket smart contract, not a user wallet",
"is_contract": true,
"contract_type": "NegRisk CTF V2 Exchange", // or CTF Exchange V1/V2, NegRisk CTF V1
"address": "0xe2222d279d744050d28e00520010520000310f59"
}Currently 4 addresses excluded: 0x4bfb41d5... (CTF Exchange V1), 0xc5d563a3... (NegRisk CTF V1), 0xe1111800... (CTF Exchange V2), 0xe2222d27... (NegRisk CTF V2).
Rate limits
Each Premium API key is limited to 600 requests/minute (sliding window 60s; your exact cap is reported in the X-RateLimit-Limit header). Anonymous public read endpoints are Cloudflare-throttled per IP (Premium keys have no daily cap; normal browsing on this site is unaffected). Custom enterprise tier available on request. Usage headers on every response:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599Batch endpoints: POST /api/public/v1/wallets/overview (max 50 wallets) and POST /api/public/v1/wallets/positions (max 20, heavier payloads) with body {"wallets": ["0x...", ...]} return per-wallet statuses (ok / computing / not_found) in one call. Batch requests are read-only and idempotent โ identical requests return the same data and never mutate state, so retrying after a timeout or network error is always safe. One batch consumes N (= wallet count) of the per-key budget; the X-RateLimit-Consumed header reports it. Wallets in computing status are queued automatically and typically resolve within minutes; for an immediate result fetch the single-wallet overview endpoint.
Need higher limits? Email support@orcalayer.com with your use case.
Two layers of data
Most endpoints return netted, human-readable data โ start there. One advanced endpoint exposes the raw on-chain event stream for builders who want to do their own aggregation.
Layer 1 โ Positions & performance (use this for most things)
- โข
/wallet/{addr}/overviewโ P&L, win rate, volume, profit factor - โข
/wallet/{addr}/positionsยท/wallet/{addr}/closedโ open & closed positions - โข
/whale/{addr}/backtestโ resolved positions for backtesting (avg entry, net cost, P&L, won/lost) - โข
/whales/leaderboard,/whales/recent-trades
Netted, NegRisk-corrected, farmer-filtered. Each row is a real economic position.
Layer 2 โ Raw trade events (advanced)
/wallet/{addr}/trades returns raw fills. Each row carries an entry_type โ the settlement mechanics of the CLOB match, not trader intent:
- โข
MINTโ the order matched an opposite-side buyer: no seller was in the book, so the protocol minted a new YES+NO pair and split it between the two counterparties (each side receives one leg) - โข
COMPLEMENTARYโ the order matched an existing holder: tokens simply changed hands - โข
MERGEโ two sells matched: the pair was burned back to USDC - โข
nullโ legacy V1 orderbook trade (before the 2026-04-28 cutover)
~80% of all fills are MINT โ the label depends on who happened to be on the other side at that millisecond. A MINT fill does not mean the wallet deliberately split collateral (deliberate on-chain splits are not orderbook fills and never appear here). side is the direction of the CTF operation, not an exchange buy/sell. Full market-wide history is solid from ~Oct 2025; older data is progressively thinner. For copy-trade backtesting prefer Layer 1.
Endpoints
https://orcalayer.com/api/public/v1/whales/leaderboard?limit=10&sort=pnlTop whales ranked by the chosen metric. Params: limit (1-100), sort (pnl | win_rate | volume | trades), min_profit_factor, min_markets, min_wr, min_pnl, max_avg_entry, category, filter (smart | all).
{
"whales": [
{
"wallet": "0x56687bf447db6ffa42ffe2204a05edaa20f55839",
"name": "Theo4",
"total_pnl": 22053933.75, // Polymarket lifetime PnL when synced
"win_rate": 81.8, // from closed-positions cache when complete
"profit_factor": 99.99, // capped at 99.99 (real ratio may be higher)
"resolved_markets": 22,
"wins": 18,
"losses": 4,
"total_volume": 52213734.76,
"total_trades": 39067,
"main_category": "POLITICS",
"avg_entry_price": 0.5523,
"last_trade_ts": 1731476951,
"active_count": 0,
"market_win_rate": 85.7, // per-market basis (1 unit per market)
"market_wins": 12,
"market_losses": 2,
"mint_volume_30d": 0.0,
"merge_volume_30d": 0.0
}
],
"total": 193696,
"sort": "pnl",
"offset": 0
}https://orcalayer.com/api/public/v1/wallet/{address}/overviewFull profile + aggregate stats for any Polygon wallet (0xโฆ or Polymarket username). Primary stats are served from a per-wallet cache (see as_of field, refreshed within ~5 min of trading activity). On a cold cache for a very heavy wallet the API may return HTTP 202 + Retry-After: 30 โ retry once and the cache will be warm. Under heavy load, secondary counters (active_count, closed_count, W/L breakdowns) may be omitted (null) with top-level degraded: true โ primary stats are always served. view=union and view=signer are computed live and may be slower.
{
"profile": {
"address": "0x56687bf447db6ffa42ffe2204a05edaa20f55839",
"name": "Theo4",
"pseudonym": "Ironclad-Tenement",
"proxy_wallet": "0x56687bf447db6ffa42ffe2204a05edaa20f55839"
},
"overview": {
"total_trades": 39067,
"total_markets": 14,
"total_volume": 52213734.76,
"last_trade": 1731476951,
"profit_factor": 99.99, // cache PnL ratio when complete
"active_count": 0, // currently held positions
"closed_count": 22, // matches stats.wins + stats.losses
"median_hold_days": 21.5, // typical days a position is held (last 90d window)
"hold_positions_count": 12 // sample size that produced median (3+ required)
},
"stats": {
"resolved": 22,
"wins": 18, // from closed-positions cache; per-market fallback for heavy wallets
"losses": 4,
"win_rate": 81.8,
"total_pnl": 22053933.75, // Polymarket lifetime PnL (their leaderboard/profit endpoint)
"profit_factor": 99.99,
"is_smart": true,
"profitable_streak": 1,
"market_win_rate": 85.7,
"market_wins": 12,
"market_losses": 2,
"unrealized_pnl": 0,
"pnl_24h": null
},
"rankings": {
"rank_pnl": 1,
"rank_winrate": 48344,
"rank_volume": 125,
"rank_profit_factor": 7,
"total_traders": 1298302,
"is_smart": true
},
"categories": {
"SPORTS": 0.0, "GEOPOLITICS": 0.0, "CRYPTO": 0.0,
"POLITICS": 85.7, "ECONOMICS": 0.0, "TECH": 0.0
},
"as_of": 1765538538, // unix ts of the cached snapshot
"degraded": false // true = secondary counters omitted under load
}https://orcalayer.com/api/public/v1/wallet/{address}/positions?limit=50Open positions for the wallet with current P&L. Returns the full open-position set in one response โ the limit/offset params are accepted but not currently enforced, and order is not guaranteed, so sort client-side (e.g. by current_value).
{
"positions": [
{
"question": "Spread: Colombia (-1.5)",
"condition_id": "0xba9f8cf5...",
"market_id": "2099029",
"slug": "fifwc-col-gha-2026-07-03-spread-home-1pt5",
"side": "token2", // token1 = YES leg, token2 = NO leg
"outcome": "No",
"tokens": 155629.0, // shares held
"avg_entry": 0.64, // average entry price
"current_price": 0.625,
"current_value": 97268.12,
"cost": 99602.56,
"initial_value": 99602.56,
"pnl": -2334.43,
"pnl_pct": -2.3,
"category": "SPORTS",
"last_trade_ts": 1751558400
}
],
"source": "merged", // provenance: "merged" = live overlay + cache
"is_estimated": false, // true when values are DB-estimated (overlay not fresh)
"count": 1
}https://orcalayer.com/api/public/v1/market/{market_id}Market details + smart whale consensus + 3 trader rankings (Smart / Top Size / Top Shares). Each ranking has list of top 10 + aggregate metrics (count, invested, avg WR, agg P&L). yes_team_shares / no_team_shares added 2026-05-06 โ sorts by share count (matches Polymarket UI Top Holders order).
{
"market": {
"id": "2099029",
"question": "US x Iran permanent peace deal by May 15, 2026?",
"price_yes": 0.085,
"price_no": 0.915,
"category": "GEOPOLITICS",
"volume": 65397286.0
},
"whales": { "yes": 321, "no": 474, "total": 795, "yes_pct": 40.4 }, // smart-whale head-count per side; yes_pct = consensus lean (0-100)
// Smart Money tab โ only smart whales, sorted by USD invested
"yes_team": [...], "no_team": [...],
"yes_team_total_count": 321, "no_team_total_count": 474,
"yes_team_total_invested": 217400, "no_team_total_invested": 1730000,
"yes_team_avg_wr": 67.0, "yes_team_agg_pnl": -117300, "yes_team_agg_pnl_pct": -23.8,
// Top Size tab โ all traders, sorted by USD invested
"yes_team_size": [...], "no_team_size": [...],
"yes_team_size_total_count": 2391, "yes_team_size_avg_wr": 36.5,
"yes_team_size_agg_pnl": -117300, ...
// Top Shares tab โ all traders, sorted by share count (added 2026-05-06)
"yes_team_shares": [
{ "wallet": "0xc851...", "name": "betwick",
"side": "YES", "shares": 246169, "avg_price": 0.119,
"cost": 29368, "pnl": 3234, "pnl_pct": 11.0,
"win_rate": 60.0, "global_pnl": 285000, "is_smart": false }
],
"no_team_shares": [...],
"yes_team_shares_avg_wr": 35.2, "no_team_shares_avg_wr": 47.1,
"yes_team_shares_agg_pnl": ...,
...
}https://orcalayer.com/api/public/v1/whale-flips?days=1&limit=20Smart whales that reversed direction (sign flip) on a market in the last 24h. Compares today vs an N-days-ago snapshot. $200K+ swing required to qualify. Historical N up to 14 days. Strong drama signal โ the whale changed conviction.
{
"flips": [
{
"wallet": "0x...",
"display_name": "Brokie",
"market_id": "1808970",
"old_side": "YES",
"new_side": "NO",
"old_size_usd": 500000,
"new_size_usd": 700000,
"swing_usd": 1200000,
"win_rate": 75.7,
"lifetime_pnl": 1900000
}
],
"count": 1,
"lookback_days": 1
}https://orcalayer.com/api/public/v1/conviction-clusters?min_whales=3&limit=10Conviction clusters โ events where 3+ smart whales aligned same side across 2+ related markets. Aggregate signal stronger than single-market position. Returns event group, side (YES/NO), whale count, market count, combined capital.
{
"clusters": [
{
"event_slug": "presidential-election-winner-2028",
"side": "NO",
"whale_count": 13,
"market_count": 3,
"total_capital_usd": 5458963,
"whales": [{"name": "Kickstand7", "wr": 63.5, "pnl": 1402041}, ...],
"markets": [{"market_id": "123", "question": "..."}]
}
],
"count": 1
}https://orcalayer.com/api/public/v1/isw/statusISW Territory Monitor โ all tracked cities with per-market subscriptions. Each city has 1+ subscriptions (single landmark, any-territory polygon, or capture-all polygon). Each subscription has its own threat level computed from polygon intersection with combined ISW shading (control + advance + gains_24h).
{
"summary": {
"total_cities": 51,
"total_subscriptions": 62,
"captured_subscriptions": 2,
"threats_by_subscription": { "CRITICAL": 2, "HIGH": 8, ... }
},
"cities": {
"Kupiansk-Vuzlovyi": {
"coordinates": { "lon": 37.6439, "lat": 49.6605 },
"worst_threat": "SAFE",
"last_check": "2026-07-01T19:50:30",
"subscriptions": [
{
"id": 5,
"label": "Any territory",
"check_type": "enter",
"geometry": [[37.644, 49.673], ...], // closed-ring polygon
"threat": "SAFE",
"coverage": 0.0, // 0..1 polygon area shaded
"closest_distance_m": 3666, // distance to nearest shading
"market_slug_pattern": "will-russia-enter-kupiansk-vuzlovyi-by-*",
"description_excerpt": "Russia captures any territory of Kupiansk-Vuzlovyi...",
"market": { "id": "...", "question": "...", "price_yes": 1.0, "volume": 10652 }
},
{
"id": 6,
"label": "Railroad station",
"check_type": "single",
"geometry": [[37.644326, 49.654359]], // single point
"buffer_advance_m": 250,
"threat": "SAFE",
"point_shaded": false,
"closest_distance_m": 5646,
"market_slug_pattern": "will-russia-capture-kupiansk-vuzlovyi-by-*",
"description_excerpt": "Russia captures the Kupyansjk-Vuzlovij railroad station..."
}
]
}
}
}https://orcalayer.com/api/public/v1/wallet/{addr}/tradesPremium: full raw trade feed for a wallet across all markets. Rows are raw fills โ entry_type is the settlement mechanics of the match, NOT trader intent: MINT (matched an opposite-side buyer โ the protocol minted a new pair and split it between the two counterparties), MERGE (two sells matched โ pair burned back to USDC), COMPLEMENTARY (matched an existing holder โ tokens changed hands), or null for legacy V1 orderbook trades before the 2026-04-28 indexer cutover. ~80% of fills are MINT; it does not mean the wallet deliberately split collateral. 'side' is the direction of that CTF operation (maker/taker direction), NOT a plain orderbook buy/sell. Params: since (unix ts lower bound, default = last 30 days; pass since=1 for full archive), before (unix ts upper bound โ use for date-range / cursor paging), limit (default 100, max 500), offset. Auth: Premium key (Bearer or x-api-key). Note: history before ~Oct 2025 is sparse (pre-Alchemy backfill).
Authorization: Bearer sk_orca_XXXXXX
GET /api/public/v1/wallet/0xabc.../trades?since=1&limit=50
{
"count": 50,
"has_more": true,
"trades": [
{
"condition_id": "0x6889...",
"market_id": "2680257",
"side": "BUY",
"outcome": "No",
"size": 10146.1,
"price": 0.48,
"usd_amount": 4870.13,
"timestamp": 1782673162,
"transaction_hash": "0x5be0...",
"entry_type": "MINT",
"title": "Will Canada win on 2026-06-28?",
"slug": "fifwc-rsa-can-2026-06-28-can"
}
]
}https://orcalayer.com/api/public/v1/wallet/{addr}/market-tradesPremium: historical trades for wallet+market+time slice (same CTF-event semantics as the full feed). Required: market (condition_id), before (unix ts). Optional: after (default 0 = from start), limit (default 100, max 500). Auth: Bearer Premium key. Performance note: omitting after on busy wallets does a full scan (~25s); for fast queries pass a narrow time window (e.g. last 7 days).
Authorization: Bearer sk_orca_XXXXXX
GET /api/public/v1/wallet/0xabc.../market-trades?market=0xcond...&before=1777000000&after=1776900000&limit=50
{
"wallet": "0xabc...",
"market": "0xcond...",
"count": 12,
"trades": [
{
"id": 588001234,
"timestamp": 1776999500,
"wallet_role": "maker",
"direction": "BUY",
"side": "YES",
"price": 0.245,
"usd_amount": 612.5,
"token_amount": 2500,
"entry_type": "MINT",
"tx_hash": "0xab09...",
"counterparty": "0xdef..."
}
]
}https://orcalayer.com/api/public/v1/market/{condition_id}/whale-tradesPremium: whale-class trades on a market (either maker or taker is in smart_whales). Required: before (unix ts). Optional: min_usd (default 500 โ also echoed in response), limit (default 100, max 500). Auth: Bearer Premium key. Performance: ~10-15s on busy markets (resolves condition_id โ market_id internally, 20s statement timeout protects against runaway).
Authorization: Bearer sk_orca_XXXXXX
GET /api/public/v1/market/0xcond.../whale-trades?before=1777000000&min_usd=1000&limit=50
{
"market": "0xcond...",
"count": 23,
"trades": [
{
"timestamp": 1776999000,
"maker": "0xabc...",
"taker": "0xdef...",
"maker_is_whale": true,
"taker_is_whale": false,
"price": 0.245,
"usd_amount": 1200,
"side": "YES",
"entry_type": "MINT"
}
]
}https://orcalayer.com/api/public/v1/wallet/{addr}/market-summary/{condition_id}Premium: wallet position snapshot on a market. Without 'at': current state from wallet_market_stats (per-side YES/NO rows). With 'at=<unix_ts>': reconstructs aggregate from trades up to that timestamp. Auth: Bearer Premium key.
Authorization: Bearer sk_orca_XXXXXX
GET /api/public/v1/wallet/0xabc.../market-summary/0xcond...?at=1776999000
{
"wallet": "0xabc...",
"condition_id": "0xcond...",
"at": 1776999000,
"found": true,
"sides": {
"YES": {
"buy_tokens": 2500, "buy_cost_usd": 612.5,
"sell_tokens": 0, "sell_cost_usd": 0,
"net_tokens": 2500, "net_cost_usd": 612.5,
"trade_count": 1,
"avg_entry_price": 0.245,
"first_trade_ts": 1776999500, "last_trade_ts": 1776999500
}
}
}https://orcalayer.com/api/public/v1/isw/eventsISW threat events stream โ CAPTURED, THREAT_CRITICAL, THREAT_HIGH, etc. Per-subscription. Query params: hours (default 24, max 720), limit (default 50, max 200), city, subscription_id, check_type ('single'/'enter'/'entirety'), min_severity ('SAFE'..'CRITICAL').
{
"events": [
{
"id": 749,
"city": "Kindrashivka",
"event_type": "CAPTURED",
"severity": "CRITICAL",
"details": "Kindrashivka (Any territory) captured",
"timestamp": "2026-07-01 19:49:26.631036",
"subscription_id": 51,
"subscription_label": "Any territory",
"check_type": "enter",
"market_slug_pattern": "will-russia-enter-kindrashivka-by-*",
"coverage": 0.058,
"closest_distance_m": 0
}
],
"count": 1
}https://orcalayer.com/api/public/v1/isw/premium/statusPremium-tier mirror of /isw/status (Bearer auth). Same payload.
Authorization: Bearer sk_orca_XXXXXXhttps://orcalayer.com/api/public/v1/isw/premium/eventsPremium-tier mirror of /isw/events (Bearer auth). Same query params and payload.
Authorization: Bearer sk_orca_XXXXXXhttps://orcalayer.com/api/analytics/smart-money-flowFree, no key. Smart-money volume flow by category over the last 24h vs the prior window โ where the whales are rotating capital.
GET /api/analytics/smart-money-flow
{
"flow": [
{
"category": "GEOPOLITICS",
"markets": 818,
"whales_now": 224105,
"volume_24h": 2007809.06,
"volume_prev": 1557691.04,
"volume_delta_pct": 28.9,
"wallets_24h": 43
}
]
}https://orcalayer.com/api/analytics/whale-clustersFree, no key. Markets where multiple whales are stacked on the same side right now โ combined capital and the wallets behind it.
GET /api/analytics/whale-clusters
{
"clusters": [
{
"market_id": "1897306",
"question": "Will Korea Republic win on 2026-06-24?",
"category": "SPORTS",
"side": "token2",
"whale_count": 8,
"combined_usd": 59852.27,
"wallets": [{ "wallet": "0x0346...", "name": "GoalLineGhost" }]
}
]
}https://orcalayer.com/api/analytics/top-moversFree, no key. Wallets with the biggest PnL swing in the recent window, with a sparkline of their trajectory.
GET /api/analytics/top-movers
{
"winners": [
{
"wallet": "0xa5ea...",
"display_name": "bossoskil1",
"pnl_now": -3672577.64,
"delta": 5987768.15,
"win_rate": 48.2,
"closed_count": 1752,
"sparkline": [-9660345, -3401876, -3672577]
}
]
}https://orcalayer.com/api/analytics/whale-volume-24hFree, no key. Hourly YES/NO whale volume and trade counts over the last 24h โ a heartbeat of smart-money activity.
GET /api/analytics/whale-volume-24h
{
"series": [
{ "hour": "2026-06-22T17:00:00Z", "yes_volume": 2843611.57, "no_volume": 4400535.67, "trades": 1555 }
]
}https://orcalayer.com/api/v2/wallet/{addr}/similar-tradersFree, no key. Wallets that trade like this one โ same categories, comparable profile โ for discovery and copy-candidate research.
GET /api/v2/wallet/0xabc.../similar-traders
{
"wallet": "0xabc...",
"primary_category": "CRYPTO",
"similar": [
{
"wallet": "0x55be...",
"name": "coinman2",
"profit_factor": 1.19,
"win_rate": 57.5,
"shared_categories": ["CRYPTO"],
"overlap_label": "Crypto"
}
]
}https://orcalayer.com/api/v2/conviction-clustersPremium (X-API-Key). Events where a cohort of profitable whales agrees on one side โ 'where the smart money is convinced', with each whale's win-rate and PnL.
X-API-Key: sk_orca_XXXXXX
GET /api/v2/conviction-clusters
{
"clusters": [
{
"event_slug": "presidential-election-winner-2028",
"side": "NO",
"whale_count": 20,
"market_count": 3,
"total_capital_usd": 5756923.05,
"whales": [{ "wr": 60.5, "pnl": 667926, "name": "11122", "wallet": "0x011f..." }]
}
]
}https://orcalayer.com/api/v2/wallet/{addr}/ai-analysisPremium (X-API-Key). LLM-generated dossier on a wallet โ trading style, edges, risks. Async: the first call queues generation, poll again after ~60s for the finished report.
X-API-Key: sk_orca_XXXXXX
GET /api/v2/wallet/0xabc.../ai-analysis
# first call queues it:
{ "status": "pending", "retry_after_seconds": 60 }
# poll again after ~60s for the finished dossierhttps://orcalayer.com/api/v2/whale/{addr}/backtestPremium (X-API-Key). Per-position resolved history for a whale โ entry price, net cost, realized PnL, won/lost โ to backtest a copy strategy.
X-API-Key: sk_orca_XXXXXX
GET /api/v2/whale/0xabc.../backtest
{
"wallet": "0xabc...",
"positions": [
{
"market_id": "2132768",
"question": "Will Bitcoin reach $150,000 in May?",
"side": "NO",
"avg_entry_price": 0.9971,
"net_cost": 606386.01,
"pnl": 870.29,
"won": true,
"category": "CRYPTO"
}
]
}https://orcalayer.com/api/v2/whale/{addr}/historyPremium (X-API-Key). Whale summary (PnL, win-rate, profit-factor) plus full resolved-market history.
X-API-Key: sk_orca_XXXXXX
GET /api/v2/whale/0xabc.../history
{
"whale": {
"wallet": "0xabc...",
"name": "LucasMeow",
"total_pnl": 376215.57,
"win_rate": 97.5,
"profit_factor": 174.91,
"resolved_markets": 161
},
"history": [{ "market_id": "2410563", "question": "Will Bitcoin reach $87,500 in June?", "category": "CRYPTO", "side": "NO" }]
}https://orcalayer.com/api/v2/whale-alerts/big-positionsPremium (X-API-Key). Largest open whale positions right now โ size, entry vs current price, cost basis and live value.
X-API-Key: sk_orca_XXXXXX
GET /api/v2/whale-alerts/big-positions
{
"items": [
{
"wallet": "0x1887...",
"wallet_name": "tubeyou",
"market_title": "Will Manchester City FC win on 2026-05-19?",
"side": "Yes",
"size": 8269545.6,
"avg_price": 0.6092,
"current_price": 0.305,
"cost_basis": 5037807.0
}
]
}https://orcalayer.com/api/v2/whale-alerts/summaryPremium (X-API-Key). Rolling stat-strip over a window (default 1440 min): total alerts, total volume, biggest single move, most active whale.
X-API-Key: sk_orca_XXXXXX
GET /api/v2/whale-alerts/summary?minutes=1440
{
"window_minutes": 1440,
"total_alerts": 13016,
"total_volume": 57294668.26,
"biggest_single": { "usd_amount": 423955.91, "question": "Argentina vs. Austria: O/U 2.5" },
"most_active_whale": { "name": "swisstony", "trades": 4169 }
}https://orcalayer.com/api/v2/isw/webhook/registerPremium (X-API-Key). Subscribe a URL to receive ISW Ukraine territory events as they publish โ push instead of poll. Body: url (required), cities ('all' or comma-separated). Unregister: DELETE /api/v2/isw/webhook/unregister with the same body.
X-API-Key: sk_orca_XXXXXX
Content-Type: application/json
POST /api/v2/isw/webhook/register
{ "url": "https://your-server.com/hook", "cities": "all" }
{ "status": "registered", "url": "https://your-server.com/hook", "cities": "all" }Real-time trade stream (SSE)
Server-Sent Events stream of every Polymarket trade event. Our relay forwards events sub-second from Polymarket's on-chain confirmation. Polymarket V2 batches trade submissions on-chain every ~60โ120 seconds (gas optimization) โ this is the structural settlement window inherited by all on-chain data sources, including ours. Use it for copy-trading bots, live dashboards, or any consumer that would otherwise poll.
https://orcalayer.com/api/public/v1/live/tradesStreams one event: trade frame per fill. Keep the connection open; the server sends : keepalive comments every 15s when the upstream is quiet.
NEW (22.07.2026): every event now carries settlement_type โ"MINT" | "MERGE" | "COMPLEMENTARY" | null โ derived live by grouping fills of the same transactionHash in a fixed 700ms buffer (settlement_hold_ms), ~60โ120s before the trade appears on-chain. Shadow-verified against on-chain OrdersMatched over 205,920 events: MINT/MERGE accuracy 100.000% (54,470 tx, zero mislabels), coverage 91.8%. Semantics: the label is tx-level (all fills of one match share it);COMPLEMENTARY means the tx contains a complementary component (pure-COMPL txs don't exist in V2 matching); null is an honest refusal (lone fill at the buffer edge, complex multi-match batch) โ never read it as "not a mint". Settlement mechanics, not trader intent.
curl -N -H "Authorization: Bearer sk_orca_XXXXXX" \
https://orcalayer.com/api/public/v1/live/tradesEvent payload (V2 โ recommended)
{
"asset": "54709499356...", // ERC-1155 CTF token id
"conditionId": "0xb4766e...",
"eventSlug": "btc-updown-5m-...",
"proxyWallet": "0xd9013df8...", // = maker address
"side": "BUY", // maker side
"price": 0.66, // 0.0 .. 1.0
"size": 4.06, // shares
"outcome": "Up",
"pseudonym": "Dear-Colonial",
"bio": "", // whale's social metadata
"profileImage": "",
"title": "Bitcoin Up or Down - ...",
"timestamp": 1776759129,
"transactionHash": "0xab09c4...",
"relay_received_at_ms": 1784634290778, // when our relay got it (before hold)
"settlement_type": "MINT", // MINT | MERGE | COMPLEMENTARY | null
"settlement_hold_ms": 700 // fixed derivation buffer
}Enriched fields (from our indexer)
When you query historical trade data via /wallet/{address} endpoints, each row includes these enriched fields derived from V2 OrdersMatched events:
| Field | Values | Meaning |
|---|---|---|
| entry_type | MINT | MERGE | COMPLEMENTARY | null | Settlement mechanics of the CLOB match โ not trader intent. The label depends on who happened to be on the other side at that millisecond. MINT = the order matched an opposite-side buyer: no seller was in the book, so the protocol minted a new YES+NO pair and split it between the two counterparties (each side receives one leg). ~80% of all fills. Side-signal: the order swept available liquidity โ an aggressive entry โ but it does NOT mean the wallet deliberately split collateral. MERGE = two sells matched: the pair was burned back to USDC. COMPLEMENTARY = the order matched an existing holder: tokens simply changed hands. null = V1 legacy trade (pre-cutover 2026-04-28), not classified. |
| fee_usd | number | Exchange fee in USDC. Subtract from usd_amount for exact net P&L. |
Limits
- Max 5 concurrent SSE connections per API key
- Each SSE connection counts as 1 against the 600 req/min limit (not per event)
- If upstream drops, the server auto-reconnects up to 5ร with exponential backoff before sending
event: error
Examples
import json, requests
KEY = "sk_orca_XXXXXX"
with requests.get(
"https://orcalayer.com/api/public/v1/live/trades",
headers={"Authorization": f"Bearer {KEY}"},
stream=True,
timeout=None,
) as r:
for line in r.iter_lines(decode_unicode=True):
if not line or not line.startswith("data:"):
continue
trade = json.loads(line[5:].strip())
# settlement_type is derived live (tx-level, 100.000% verified on
# MINT/MERGE). null = honest refusal, not "not a mint".
usd = trade["size"] * trade["price"]
if usd > 10_000 and trade.get("settlement_type") == "MINT":
print(f"๐ {trade['proxyWallet'][:10]}.. {trade['side']} {trade['outcome']} "
f"USD {usd:.0f} @ {trade['price']} [{trade['settlement_type']}]")
// EventSource does NOT support custom headers โ pass the key as query param
// via a thin proxy, OR use fetch() with ReadableStream:
const resp = await fetch("https://orcalayer.com/api/public/v1/live/trades", {
headers: { Authorization: "Bearer sk_orca_XXXXXX" }
});
const reader = resp.body.getReader();
const decoder = new TextDecoder();
let buf = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
const events = buf.split("
");
buf = events.pop() || "";
for (const e of events) {
const data = e.split("
").find(l => l.startsWith("data:"));
if (data) console.log(JSON.parse(data.slice(5)));
}
}Code examples
const resp = await fetch("https://orcalayer.com/api/public/v1/whales/leaderboard?limit=5", {
headers: { Authorization: "Bearer " + process.env.ORCA_KEY }
});
const data = await resp.json();
console.log(data.whales);import os, requests
headers = {"Authorization": f"Bearer {os.environ['ORCA_KEY']}"}
r = requests.get("https://orcalayer.com/api/public/v1/whales/leaderboard", params={"limit": 5}, headers=headers)
r.raise_for_status()
for w in r.json()["whales"]:
print(w["name"], w["total_pnl"])import time, requests
headers = {"Authorization": "Bearer sk_orca_XXXXXX"}
while True:
resp = requests.get("https://orcalayer.com/api/public/v1/market/1919417", headers=headers, timeout=15)
resp.raise_for_status()
whales = resp.json()["whales"] # {"yes", "no", "total", "yes_pct"}
print(f"smart-money YES={whales['yes_pct']:.1f}% ({whales['yes']} yes / {whales['no']} no)")
time.sleep(60) # once per minute, well under 600/min limitError responses
| Status | Meaning |
|---|---|
| 401 | Missing, invalid, or revoked API key (on key-gated endpoints; public reads need no key) |
| 403 | Key valid but user's plan is not Premium |
| 404 | Endpoint not in public whitelist, or resource not found |
| 429 | Rate limit exceeded โ wait Retry-After seconds |
| 502 | Upstream data service temporarily unavailable |
Ready to build?
Premium unlocks the full API, SSE live feed, and priority support.
Upgrade to Premium โ $19.99/moQuestions? support@orcalayer.com