Skip to main content

API reference

Idmon API — Documentation

Calibrated, real-time prediction-market intelligence — delivered as signed webhooks, a WebSocket stream, and a REST API. Base URL: https://api.idmon.io.

Get started

Quickstart

Three steps from zero to live data.

Get your key

Email hello@idmon.io to request access. Tell us your use case and we'll confirm the right tier, provision your API key, and — for Operator — configure your webhook. Usually within one business day.

Request access

Make your first call (Developer)

Once you have a key, fetch recent signal alerts:

shell
curl -s https://api.idmon.io/api/alerts/recent?limit=5 \
  -H "Authorization: Bearer pmp_dev_your_key_here"

Example response:

json
[
  {
    "conditionId": "0xabc123...",
    "alertType": "whale_trade",
    "question": "Will the Fed cut rates in July 2026?",
    "category": "economics",
    "currentPrices": { "Yes": 0.62, "No": 0.38 },
    "priceChangePct": 4.8,
    "volume24h": 1240000,
    "sentAt": "2026-06-19T10:14:22Z",
    "message": "Whale bought $85K YES at 0.62"
  }
]

Receive data

Operator: We configure signed webhooks to push signal embeds directly to your Discord channel or endpoint — within ~1.5 s of an alert. See Webhooks for the payload contract and signature verification.

Developer: Connect the WebSocket stream for a live push of every alert as it fires. See WebSocket for the connect URL, message types, and a Node.js example.

Authentication

All REST endpoints require your API key as a Bearer token in the Authorization header. Do not pass it as a query parameter for REST.

http header
Authorization: Bearer <your-api-key>

WebSocket connections authenticate via a ?key= query parameter on the connect URL (bearer headers are not supported at the WS handshake — see WebSocket).

Key prefixes

Your key prefix tells you which tier you're on:

Prefix Tier
pmp_op_ Operator
pmp_dev_ Developer
pmp_ent_ Enterprise
Invalid or over-limit keys return 401 Unauthorized. If you see a 401 mid-session your daily quota may have reset — check your usage against the rate limits table.

REST API

Base URL: https://api.idmon.io. Every /api/* path requires the Authorization: Bearer <key> header. Responses are JSON. Errors follow standard HTTP status codes.

GET /api/health any tier

Returns service status, uptime, your tier, rate-limit headroom, and server memory. Use this to confirm connectivity and inspect your plan limits.

shell
curl -s https://api.idmon.io/api/health \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
{
  "status": "ok",
  "tier": "developer",
  "uptime": 432800,
  "rateLimit": { "remaining": 9741, "limit": 10000, "resetsAt": "2026-06-20T00:00:00Z" },
  "memoryMb": 182,
  "ts": "2026-06-19T11:04:00Z"
}
GET /api/alerts/recent Developer+

Returns recent signal alerts, newest first. The quickstart example uses this endpoint.

Query param Type Description
limitdefault 50 integer Maximum number of alerts to return.
type string Filter by alert type, e.g. whale_trade, volume_surge.
shell
curl -s "https://api.idmon.io/api/alerts/recent?limit=50&type=whale_trade" \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
[
  {
    "conditionId": "0xabc123...",
    "alertType": "whale_trade",
    "question": "Will the Fed cut rates in July 2026?",
    "category": "economics",
    "currentPrices": { "Yes": 0.62, "No": 0.38 },
    "priceChangePct": 4.8,
    "volume24h": 1240000,
    "sentAt": "2026-06-19T10:14:22Z",
    "message": "Whale bought $85K YES at 0.62"
  }
]
GET /api/alerts/counts Developer+

Returns a histogram of alert counts by type over the requested window. Useful for building dashboards or spotting unusual activity.

Query param Type Description
hoursdefault 24 integer Window size in hours to aggregate over.
shell
curl -s "https://api.idmon.io/api/alerts/counts?hours=24" \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
{
  "hours": 24,
  "counts": {
    "whale_trade": 18,
    "volume_surge": 7,
    "price_spike": 3
  },
  "since": "2026-06-18T11:00:00Z"
}
GET /api/whales/recent Developer+

Recent large-trade events, each with side, size, and whale/mega-whale classification.

Query param Type Description
limitdefault 20 integer Maximum number of events to return.
shell
curl -s "https://api.idmon.io/api/whales/recent?limit=20" \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
[
  {
    "side": "YES",
    "sizeUsd": 150000,
    "price": 0.71,
    "question": "Will BTC close above $100K in June?",
    "category": "crypto",
    "timestamp": "2026-06-19T09:52:11Z",
    "isMegaWhale": true
  }
]
GET /api/whales/stats Developer+

Aggregate whale statistics — total all-time, mega-whale count, and rolling 24-hour volume.

shell
curl -s https://api.idmon.io/api/whales/stats \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
{
  "totalWhaleAlerts": 4120,
  "megaWhaleAlerts": 312,
  "whaleAlerts24h": 18
}
GET /api/markets/top Developer+

Top markets by 24-hour volume, with current outcome prices and liquidity. Optionally filter by category.

Query param Type Description
limitdefault 20 integer Maximum number of markets to return.
category string Filter by category slug, e.g. politics, crypto, economics.
shell
curl -s "https://api.idmon.io/api/markets/top?limit=20&category=politics" \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
[
  {
    "conditionId": "0xdef456...",
    "question": "Will Labour win the next UK general election?",
    "category": "politics",
    "endDate": "2029-01-31T00:00:00Z",
    "volume24h": 3100000,
    "liquidity": 820000,
    "outcomePrices": { "Yes": 0.54, "No": 0.46 },
    "url": "https://polymarket.com/event/..."
  }
]
GET /api/wallets/top Developer+

Top-performing wallets ranked by win rate, with trade counts, streaks, and total volume.

Query param Type Description
ndefault 20 integer Number of wallets to return.
shell
curl -s "https://api.idmon.io/api/wallets/top?n=20" \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
[
  {
    "walletAddress": "0x1a2b3c...",
    "username": "sharpshooter",
    "correctTrades": 84,
    "totalTrades": 102,
    "winRate": 0.824,
    "currentStreak": 7,
    "totalVolumeUsd": 540000,
    "polymarketUrl": "https://polymarket.com/profile/0x1a2b3c..."
  }
]
GET /api/overview Developer+

A single-request dashboard summary — alert and whale counts over 24 hours, and the number of currently active markets.

shell
curl -s https://api.idmon.io/api/overview \
  -H "Authorization: Bearer pmp_dev_your_key_here"
json — example response
{
  "alertCount24h": 28,
  "whaleCount24h": 18,
  "activeMarkets": 3142,
  "ts": "2026-06-19T11:04:00Z"
}

WebSocket

Available on Developer and Enterprise plans. Connect once to receive every alert as it fires — no polling, no batch lag.

Connect URL

url
wss://api.idmon.io/ws?key=<your-api-key>&types=volume_surge,whale_trade&minVolume=50000
Param Required Description
key Yes Your API key (Developer or Enterprise prefix).
types No Comma-separated alert types to filter. Omit to receive all types.
minVolume No Minimum 24h market volume (USD) to filter alerts.

Message types

json — connected (on open)
{ "type": "connected", "message": "Authenticated. Stream active." }
json — alert
{
  "type": "alert",
  "data": {
    "alertType": "whale_trade",
    "conditionId": "0xabc123...",
    "question": "Will the Fed cut rates in July 2026?",
    "category": "economics",
    "currentPrices": { "Yes": 0.62, "No": 0.38 },
    "priceChangePct": 4.8,
    "volume24h": 1240000,
    "message": "Whale bought $85K YES at 0.62",
    "timestamp": "2026-06-19T10:14:22Z"
  }
}
json — ping (every 30 s)
{ "type": "ping" }
Keepalive: The server sends a ping frame every 30 seconds. Clients should ignore it — no pong response is required. If you lose the connection, reconnect with the same URL.

Close codes

4001 Unauthorized — missing, invalid, or expired API key.
4003 Plan restriction — your tier does not include WebSocket access.
4008 Connection limit reached — you have too many concurrent WebSocket connections for your tier.

Node.js example

javascript
import WebSocket from 'ws';

const KEY = process.env.IDMON_API_KEY;
const url = `wss://api.idmon.io/ws?key=${KEY}&types=whale_trade,volume_surge&minVolume=50000`;

function connect() {
  const ws = new WebSocket(url);

  ws.on('open', () => {
    console.log('WebSocket open — waiting for alerts...');
  });

  ws.on('message', (raw) => {
    const msg = JSON.parse(raw.toString());

    if (msg.type === 'ping') return; // ignore keepalive

    if (msg.type === 'alert') {
      const { alertType, question, message, timestamp } = msg.data;
      console.log(`[${timestamp}] ${alertType}: ${question}`);
      console.log(`  ${message}`);
    }

    if (msg.type === 'connected') {
      console.log('Authenticated:', msg.message);
    }
  });

  ws.on('close', (code, reason) => {
    if (code === 4001) { console.error('Unauthorized — check your API key'); return; }
    if (code === 4003) { console.error('WebSocket not available on your plan'); return; }
    if (code === 4008) { console.error('Connection limit reached — reduce concurrent connections'); return; }
    // Reconnect on unexpected closure
    console.warn(`Closed (${code}): ${reason}. Reconnecting in 5s...`);
    setTimeout(connect, 5000);
  });

  ws.on('error', (err) => console.error('WS error:', err.message));
}

connect();

Webhooks

Available on Operator and above. We send signed HTTP POST requests to your endpoint within ~1.5 seconds of an alert — no polling required. Discord webhook URLs receive a Discord-formatted embeds payload automatically; all other URLs receive the generic JSON below.

Generic JSON payload

json
{
  "schema": 1,
  "event": "whale_trade",
  "id": "evt_01j9abc...",
  "ts": "2026-06-19T10:14:22Z",
  "conditionId": "0xabc123...",
  "data": {
    "question": "Will the Fed cut rates in July 2026?",
    "slug": "fed-rate-cut-july-2026",
    "category": "economics",
    "message": "Whale bought $85K YES at 0.62",
    "currentPrices": { "Yes": 0.62, "No": 0.38 },
    "previousPrices": { "Yes": 0.57, "No": 0.43 },
    "priceChangePct": 4.8,
    "volume24h": 1240000,
    "liquidity": 310000,
    "polymarketUrl": "https://polymarket.com/event/fed-rate-cut-july-2026"
  }
}

Request headers

Header Value / purpose
Content-Type application/json
X-PMP-Signature sha256=<hex> — HMAC-SHA256 of the raw request body with your webhook secret. Verify this before processing.
X-PMP-Delivery-Id Unique ID per delivery — use for idempotency (retries send the same ID).
User-Agent PMP-Webhooks/1.0

Signature verification

Always verify against the raw request body, not re-serialised JSON. Key ordering differences will break the HMAC check.
python
import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
WEBHOOK_SECRET = b"your_webhook_secret_here"

@app.route("/webhook", methods=["POST"])
def webhook():
    sig_header = request.headers.get("X-PMP-Signature", "")
    if not sig_header.startswith("sha256="):
        abort(400, "Missing signature")

    received_sig = sig_header[len("sha256="):]

    # Compute HMAC over the RAW body — do NOT re-serialise
    raw_body = request.get_data()
    expected_sig = hmac.new(WEBHOOK_SECRET, raw_body, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected_sig, received_sig):
        abort(401, "Invalid signature")

    payload = request.get_json()
    event = payload["event"]
    print(f"Verified event: {event}")

    return "", 200  # respond 2xx quickly — processing can be async

Retry behaviour

If your endpoint is unavailable or returns a non-2xx response:

  • 5xx / timeout — exponential backoff, up to 4 retry attempts.
  • 429 — backoff respects your Retry-After response header.
  • Other 4xx — permanent failure; no retries. Respond 2xx quickly and handle processing asynchronously.

Use the X-PMP-Delivery-Id header to deduplicate retries on your side.

Rate limits

Exceeding any limit returns 429 Too Many Requests. Daily request counts reset at UTC midnight.

Tier REST WebSocket Requests / day Req / second Concurrent WS Bulk history
Operator Push only
Developer 10,000 10 5
Enterprise Unlimited 50 25

Operator tier receives data exclusively via push (signed webhooks / Discord embeds) — no REST or WebSocket access. Enterprise bulk history includes market snapshots (~8K rows/min) and 5-minute OHLCV aggregates.

Support

Need help?

Email us at hello@idmon.io — we respond within 48 hours. Enterprise plans include priority support.

Email support

← Back to idmon.io