Webhook Payload Reference
Every event type and field your endpoint will receive. Copy the examples below to build and test your integration before connecting it to PolySpy.
Overview
When you configure a webhook URL in your PolySpy account or on an individual strategy, PolySpy sends an HTTP POST request to your endpoint for every trading event. This lets you build custom bots, log trades to a database, trigger notifications in Slack or Discord, or route signals to your own execution engine — all without sharing your Polymarket credentials with PolySpy.
Webhooks fire in both paper mode and live mode. Check the execution.is_paper field to distinguish between them.
Delivery Details
| Method | POST |
| Content-Type | application/json |
| User-Agent | PolySpy/1.0 |
| Timeout | 10 seconds per attempt |
| Retries | 3 attempts with exponential backoff (2s, 4s) |
| Success codes | Any 2xx status |
| Delivery | Fire-and-forget — does not block strategy execution |
| Dedup | Same wallet + market within 1 hour is deduplicated |
Signature Verification
If you configure a webhook secret, every request includes an X-PolySpy-Signature header containing an HMAC-SHA256 digest of the raw request body, prefixed with sha256=.
import hmac, hashlib
def verify_signature(body: bytes, secret: str, header: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header)const crypto = require("crypto");
function verifySignature(body, secret, header) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(body).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(header)
);
}Event Types
Every payload contains a top-level event, timestamp, and strategy_id field. The remaining fields depend on the event type.
| Event | Description |
|---|---|
| signal.entry | A new trading signal was detected and (optionally) executed. |
| signal.leaderboard_entry | A top-ranked leaderboard trader entered a position. |
| signal.exit | The tracked wallet exited a position, triggering a sell. |
| execution.stop_loss | A stop-loss was triggered and the position was closed. |
| execution.take_profit | A take-profit was triggered and the position was closed. |
| execution.near_resolution | A market is approaching resolution and the position was closed. |
| execution.resolution | A market has resolved and the position was settled. |
| portfolio.summary | Hourly summary of open positions and daily P&L. |
Payload Examples
Click the copy button on any example to use it for testing your endpoint.
signal.entry
Fired when a fresh wallet, leaderboard, or watchlist signal is detected. Includes the triggering trade, wallet info, market details, and execution result (if a trade was placed).
{
"event": "signal.entry",
"timestamp": "2025-04-08T14:32:01.812345+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source": "fresh_wallet",
"trade": {
"condition_id": "0xabc123def456...",
"asset": "21742633143463906290569050155826241533067272736897614950488156847949938836455",
"proxy_wallet": "0x1234567890abcdef1234567890abcdef12345678",
"side": "BUY",
"outcome": "Yes",
"size": 500,
"price": 0.62,
"size_usd": 310,
"timestamp": 1712587921,
"title": "Will BTC hit $100k by July 2025?",
"event_slug": "will-btc-hit-100k-by-july-2025",
"transaction_hash": "0xdeadbeef..."
},
"wallet": {
"address": "0x1234567890abcdef1234567890abcdef12345678",
"first_tx_timestamp": 1712584321,
"age_hours": 1,
"is_fresh": true
},
"market": {
"token_id": "21742633143463906290569050155826241533067272736897614950488156847949938836455",
"condition_id": "0xabc123def456...",
"question": "Will BTC hit $100k by July 2025?",
"slug": "will-btc-hit-100k-by-july-2025",
"event_slug": "will-btc-hit-100k-by-july-2025"
},
"execution": {
"timestamp": 1712587922,
"token_id": "21742633143463906290569050155826241533067272736897614950488156847949938836455",
"condition_id": "0xabc123def456...",
"market_question": "Will BTC hit $100k by July 2025?",
"side": "BUY",
"size_usd": 25,
"fill_price": 0.63,
"is_paper": false,
"strategy": "Fresh Whale Copy",
"order_id": "0xorder123...",
"status": "filled",
"pnl": null,
"error_message": null,
"source": "fresh_wallet",
"tracked_wallet": "0x1234567890abcdef1234567890abcdef12345678",
"event_slug": "will-btc-hit-100k-by-july-2025"
}
}signal.leaderboard_entry
Fired when a top-ranked leaderboard trader enters a position. Includes their ranking, username, and P&L alongside the trade details.
{
"event": "signal.leaderboard_entry",
"timestamp": "2025-04-08T14:35:12.654321+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source": "leaderboard",
"trade": {
"condition_id": "0xdef789abc012...",
"asset": "98765432109876543210987654321098765432109876543210987654321098765432",
"proxy_wallet": "0xabcdef1234567890abcdef1234567890abcdef12",
"side": "BUY",
"outcome": "No",
"size": 2000,
"price": 0.35,
"size_usd": 700,
"timestamp": 1712588112,
"title": "Will ETH flip BTC by 2026?",
"event_slug": "will-eth-flip-btc-by-2026",
"transaction_hash": "0xcafebabe..."
},
"leaderboard_entries": [
{
"proxy_wallet": "0xabcdef1234567890abcdef1234567890abcdef12",
"username": "whalemaster",
"pnl": 142350.75,
"rank": 3,
"time_period": "all_time"
}
],
"execution": null
}signal.exit
Fired when the original tracked wallet exits a position, triggering a matching sell on your side.
{
"event": "signal.exit",
"timestamp": "2025-04-08T18:45:30.123456+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"trade": {
"condition_id": "0xabc123def456...",
"asset": "21742633143463906290569050155826241533067272736897614950488156847949938836455",
"proxy_wallet": "0x1234567890abcdef1234567890abcdef12345678",
"side": "SELL",
"outcome": "Yes",
"size": 500,
"price": 0.78,
"size_usd": 390,
"timestamp": 1712603130,
"title": "Will BTC hit $100k by July 2025?",
"event_slug": "will-btc-hit-100k-by-july-2025",
"transaction_hash": "0xfeedface..."
},
"execution": {
"timestamp": 1712603131,
"token_id": "21742633143463906290569050155826241533067272736897614950488156847949938836455",
"condition_id": "0xabc123def456...",
"market_question": "Will BTC hit $100k by July 2025?",
"side": "SELL",
"size_usd": 25,
"fill_price": 0.77,
"is_paper": false,
"strategy": "Fresh Whale Copy",
"order_id": "0xorder456...",
"status": "filled",
"pnl": 5.56,
"error_message": null,
"source": "fresh_wallet",
"tracked_wallet": "0x1234567890abcdef1234567890abcdef12345678",
"event_slug": "will-btc-hit-100k-by-july-2025"
}
}execution.stop_loss
Fired when a position hits your configured stop-loss level. Includes the trigger type, P&L, and entry/exit prices.
{
"event": "execution.stop_loss",
"timestamp": "2025-04-08T20:12:45.987654+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"execution": {
"timestamp": 1712608365,
"token_id": "55555555555555555555555555555555555555555555555555555555555555555555",
"condition_id": "0x555aaa...",
"market_question": "Will SOL reach $200 by May?",
"side": "SELL",
"size_usd": 50,
"fill_price": 0.41,
"is_paper": false,
"strategy": "Leaderboard Copy",
"order_id": "0xorder789...",
"status": "filled",
"pnl": -9.5,
"error_message": null,
"source": "leaderboard",
"tracked_wallet": "0xabcdef1234567890abcdef1234567890abcdef12",
"event_slug": "will-sol-reach-200-by-may"
},
"trigger": "stop_loss",
"pnl": -9.5,
"pnl_percent": -19,
"entry_price": 0.5,
"exit_price": 0.41
}execution.take_profit
Fired when a position hits your configured take-profit level. Same structure as stop_loss with a different trigger.
{
"event": "execution.take_profit",
"timestamp": "2025-04-08T22:05:10.111111+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"execution": {
"timestamp": 1712615110,
"token_id": "66666666666666666666666666666666666666666666666666666666666666666666",
"condition_id": "0x666bbb...",
"market_question": "Will the Fed cut rates in June?",
"side": "SELL",
"size_usd": 30,
"fill_price": 0.82,
"is_paper": true,
"strategy": "Fresh Whale Copy",
"order_id": null,
"status": "filled",
"pnl": 6,
"error_message": null,
"source": "fresh_wallet",
"tracked_wallet": "0x9999888877776666555544443333222211110000",
"event_slug": "will-the-fed-cut-rates-in-june"
},
"trigger": "take_profit",
"pnl": 6,
"pnl_percent": 24,
"entry_price": 0.62,
"exit_price": 0.82
}execution.resolution
Fired when a Polymarket market resolves and your position is settled. Includes the final P&L and entry price.
{
"event": "execution.resolution",
"timestamp": "2025-04-09T00:00:01.000000+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"execution": {
"timestamp": 1712620801,
"token_id": "77777777777777777777777777777777777777777777777777777777777777777777",
"condition_id": "0x777ccc...",
"market_question": "Will it rain in NYC on April 8?",
"side": "SELL",
"size_usd": 15,
"fill_price": 1,
"is_paper": false,
"strategy": "Watchlist Fade",
"order_id": "0xorderaaa...",
"status": "filled",
"pnl": 7.5,
"error_message": null,
"source": "watchlist",
"tracked_wallet": "0xaaaa0000bbbb1111cccc2222dddd3333eeee4444",
"event_slug": "will-it-rain-in-nyc-on-april-8"
},
"pnl": 7.5,
"entry_price": 0.5
}portfolio.summary
Fired hourly with a snapshot of open positions, daily P&L, win rate, and trade count. The summary object fields may vary as we add more metrics.
{
"event": "portfolio.summary",
"timestamp": "2025-04-08T23:00:00.000000+00:00",
"strategy_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"summary": {
"open_positions": 4,
"total_invested": 120,
"unrealized_pnl": 8.75,
"realized_pnl_today": 14.31,
"win_rate": 0.67,
"trades_today": 6
}
}Common Field Reference
Base fields (all events)
| Field | Type | Description |
|---|---|---|
| event | string | Event type identifier |
| timestamp | string | ISO 8601 UTC timestamp |
| strategy_id | string | UUID of the strategy that generated this event |
execution object
| Field | Type | Description |
|---|---|---|
| timestamp | integer | Unix epoch seconds of the execution |
| token_id | string | Polymarket token ID (outcome share) |
| condition_id | string | Polymarket condition ID (market) |
| market_question | string | Human-readable market question |
| side | string | "BUY" or "SELL" |
| size_usd | number | Trade size in USD |
| fill_price | number | Price at which the order was filled (0-1) |
| is_paper | boolean | true if this was a simulated paper trade |
| strategy | string | Strategy name |
| order_id | string | null | Polymarket order ID (null for paper trades) |
| status | string | "filled", "partial", "error" |
| pnl | number | null | Realized P&L if this is an exit |
| error_message | string | null | Error details if status is not filled |
| source | string | "fresh_wallet", "leaderboard", "watchlist" |
| tracked_wallet | string | The wallet address that triggered this trade |
| event_slug | string | Polymarket event slug for linking |
Quick Start
- Go to Settings and enter your webhook URL (and optional secret).
- PolySpy sends a test POST to verify your endpoint is reachable.
- Activate a strategy — events start flowing immediately in both paper and live mode.
- Optionally override the webhook URL on individual strategies to route signals to different endpoints.