Skip to main content
Polymarket surveillance provides insider-like decision support: baselines, signals, and alerts derived from the Polymarket Data API. Access requires a Pro (or higher) subscription when SURVEILLANCE_REQUIRES_PRO is enabled.

1. Signals ↔ Endpoints

SignalPolymarketAPIClient methodEndpoint / paramsDerivation note
trade_countfetch_tradesGET /trades (market, asset_id, limit)Count per wallet from maker/taker/user
first_seen_ts (wallet)fetch_activityGET /activity (user, market, limit)Min timestamp; or from baseline entity_type=wallet, metric=first_seen_ts
volumefetch_live_volumeGET /markets/{id}/volume or /volumeStored in baseline entity_type=market, metric=volume
open_interestfetch_open_interestGET /markets/{id}/open-interest or /open-interestStored in baseline entity_type=market, metric=open_interest
leaderboard_rankfetch_leaderboardGET /leaderboard or GET /analytics/leaderboardOptional; limit for top N
holders_countfetch_holdersGET /holders (token_id, limit)Per outcome token
outsized_bet (derived)fetch_trades + baselinesTrade count vs baseline volume; alert when threshold exceeded
new_wallet_anomaly (derived)fetch_activity + get_wallet_first_activity_tsNew wallet with large activity
low_activity_market_move (derived)fetch_trades + fetch_live_volumePrice move with low historical volume

2. Baseline schema

ColumnTypeDescription
entity_typeString(50)"wallet", "market", "condition"
entity_idString(255)Wallet address, market id, or condition id
windowString(50)"1d", "7d", "30d"
metricString(100)"volume", "trade_count", "first_seen_ts", "open_interest", etc.
valueJSONBNumeric or object (e.g. timestamp, aggregate)
computed_atDateTimeWhen the baseline was last updated
Unique on (entity_type, entity_id, window, metric) for upsert.

3. Alert schema

ColumnTypeDescription
alert_typeString(100)"outsized_bet", "new_wallet_anomaly", "low_activity_market_move", etc.
severityString(20)"low", "medium", "high", "critical"
condition_idString(255), nullableRelated condition/market
proxy_walletString(66), nullableWallet involved
event_idString(255), nullableRelated event
signal_valuesJSONB, nullableSnapshot of signals that fired
messageTextHuman-readable description
created_atDateTimeWhen the alert was created
reviewed_atDateTime, nullableWhen it was reviewed
reviewed_byInteger, FK users, nullableReviewer user id
resolutionString(50), nullable"dismissed", "escalated", "false_positive"

4. Config

VariableDescriptionDefault
POLYMARKET_DATA_API_URLData API base (trades, activity, leaderboard, volume, open-interest)https://data-api.polymarket.com
POLYMARKET_SURVEILLANCE_ENABLEDEnable detection cycle (baselines, alerts)false
SURVEILLANCE_REQUIRES_PRORequire Pro (or higher) for surveillance routestrue
REVENUECAT_ENTITLEMENT_MARKET_INTELLIGENCEEntitlement for surveillance; if unset, uses REVENUECAT_ENTITLEMENT_PRO

5. Usage

Running the detection cycle

  • Cron / scheduled: Call POST /api/polymarket/surveillance/run-cycle (requires Pro and POLYMARKET_SURVEILLANCE_ENABLED=true). Response: { "skipped" } or { "baselines_updated", "alerts_created" }.
  • Admin / UI: Use the same endpoint from an admin or scheduled job. The PolymarketSurveillanceService.run_detection_cycle(markets=...) can be passed an optional list of market ids.

Listing and reviewing alerts

  • List: GET /api/polymarket/surveillance/alerts?severity=...&reviewed=...&limit=50&offset=0
  • Review: POST /api/polymarket/surveillance/alerts/{id}/review with body { "resolution": "dismissed" | "escalated" | "false_positive" }
The Surveillance section in the Polymarket Market Dashboard shows the SurveillanceAlertsPanel: it lists alerts, supports severity/reviewed filters, and a “Review” action with resolution dropdown. On 403 (subscription required), the panel shows an “Upgrade to Pro” CTA instead of the alerts table.