Skip to content

Generate your Agent API Key

Agent API Key generation is available on Pro and Elite. One key works for MCP server access and direct REST/API requests; Pro defaults to read-only access, while Elite can include full agent write access.

PolyTrackers API (External + AI Agent Guide)

This is the production-facing API guide for external developers and AI agents.

Sync guardrail: If REST auth, scopes, tiers, rate limits, trading semantics, or OpenAPI paths change, update the public agent skill at /skill.md in the same PR.


Scope

This guide/spec covers the full AI agent surface:

  • Auth: /api/auth/signup, /api/auth/login, /api/auth/refresh
  • Account/Tier: /api/account, /api/account/stats, /api/account/risk-profile
  • Discovery: /api/markets, /api/leaderboard, /api/clob/price, /api/trader-lookup
  • Anomalies: /api/anomalies, /api/anomalies/{id}, /api/anomalies/performance, /api/scan/trigger, /api/scan/run
  • Recommendations & activity: /api/recommendations, /api/bets/sync
  • Agent API Keys: /api/keys, /api/keys/generate, plus public feeds
  • Trading: /api/trades, /api/trade/execute, /api/trade/history, /api/trade/orders*
  • Alerts & webhooks: /api/alerts/preferences, /api/webhooks*
  • Whale service + ingest webhooks: wallets/roster/whale control + /api/whale/webhook*

Excluded intentionally:

  • /api/mock/* simulation helpers
  • /api/cron/* scheduled internal jobs
  • /api/admin/*, /api/stripe/*, /api/telegram/*, /api/onboarding/* and other UI/operator-only routes

Auth modes

1) User auth (session cookie or bearer)

Most user-scoped agent endpoints accept authenticated user context via:

  • Supabase session cookie (sb-* managed cookies)
  • Authorization: Bearer <supabase-jwt-access-token>

2) JWT-only bearer

POST /api/keys/generate strictly verifies Supabase JWT bearer identity.

3) Agent API Key bearer

Agent API Keys are prefixed ptk_ and are passed as Authorization: Bearer <agent-api-key>. The same key works for PolyTrackers MCP server access and direct REST/API requests when it has the required scopes:

  • signals:read — read-only data
  • agent:scan — scan trigger where allowed
  • trade:execute — real trade execution only, after readiness and preflight gates pass
  • agent:full — full agent/write/trade access (currently Elite-only for Agent API Keys)

Endpoints that accept Agent API Keys:

EndpointRequired scope
GET /api/anomaliessignals:read
GET /api/public/whale-signalssignals:read
GET /api/public/copy-signalssignals:read
POST /api/trade/executetrade:execute
GET /api/trade/historyagent:full
GET/POST/DELETE /api/trade/orders*agent:full

4) Service auth

For whale-service control endpoints:

  • x-whale-service-secret: <secret> or
  • Authorization: Bearer <WHALE_SERVICE_SHARED_SECRET>

5) Scan secret

POST /api/scan/run also accepts x-scan-secret: <SCAN_SECRET> (bypasses the tier gate; used by cron/internal automation).

6) Webhook signature auth

POST /api/whale/webhook requires:

  • x-alchemy-signature = HMAC_SHA256(raw_body, ALCHEMY_WEBHOOK_SIGNING_KEY)

Outbound deliveries from /api/webhooks* are signed with your configured secret as x-polytrackers-signature: sha256=<HMAC_SHA256(raw_body, secret)>.


Tier gating (important)

Effective tier resolution: a user on free with an active trial (trial_ends_at > now) is treated as pro. Tier failures return TIER_UPGRADE_REQUIRED with the required tier and an upgradeUrl.

Free

  • GET /api/trades: mock trades only, 7-day history window.
  • GET /api/anomalies: max 5 results, 7-day retention window, with a 1-hour visibility delay (detections newer than 1 hour are hidden).
  • POST /api/scan/trigger: not allowed (403).
  • POST /api/keys/generate, GET /api/keys: not allowed (403).
  • POST /api/trade/execute: session callers can execute only when the real-automation beta gate and trading-readiness checks pass. Agent API Key/MCP execution is unavailable because Agent API Keys require Pro+.
  • /api/trade/history, /api/trade/orders*: not allowed (403).
  • /api/webhooks (create): not allowed (403).
  • /api/public/whale-signals, /api/public/copy-signals: not allowed (403).

Pro

  • GET /api/trades: mock trades only, 90-day history window (type=real rejected with 403).
  • GET /api/anomalies: max 100 results, 90-day retention window, no delay.
  • POST /api/scan/trigger: allowed, rate limited to 2/hour.
  • /api/keys + POST /api/keys/generate: allowed; scopes default to signals:read, with optional trade:execute for real trade execution and agent:scan for scan automation where allowed. Limit: 2 active Agent API Keys per user for safe rotation.
  • /api/webhooks (create): up to 5 active webhooks.
  • /api/public/whale-signals, /api/public/copy-signals: not allowed (Elite only).
  • POST /api/trade/execute: session callers can execute only when the real-automation beta gate and trading-readiness checks pass. Agent API Key/MCP execution requires trade:execute scope.
  • /api/trade/history, /api/trade/orders*: not allowed.

Elite

  • Full GET /api/trades access (type=real allowed); history window unlimited.
  • GET /api/anomalies: max 200 results, full retention window.
  • POST /api/scan/trigger: allowed, rate limited to 10/hour.
  • /api/keys + POST /api/keys/generate: scopes may include signals:read, trade:execute, agent:scan, and/or agent:full. Limit: 2 active Agent API Keys per user for safe rotation.
  • /api/trade/execute, /api/trade/history, /api/trade/orders*: allowed where the route-specific readiness checks pass (trade:execute or agent:full for execute API-key auth).
  • /api/public/whale-signals, /api/public/copy-signals: allowed.
  • /api/webhooks (create): up to 50 active webhooks.

Rate limits

All Agent API Key requests are rate-limited per key (not per IP or per user), so different cloud IPs / Lambda runtimes sharing a key won't collide. Session requests are limited per user.

EndpointLimitScope
POST /api/auth/*10/minuteIP
POST /api/scan/triggerPro: 2/hour, Elite: 10/houruser
POST /api/keys/generate5/hour per useruser
POST /api/trade/execute10/minute per user + 20/minute per API keyuser + key
GET /api/public/whale-signals120/minute per API keyAPI key
GET /api/public/copy-signals120/minute per API keyAPI key

429 response shape

All rate-limited responses include a Retry-After header (seconds) and a structured JSON body so automated clients can back off correctly:

json
{
  "error": "This API key has exceeded its trade execution rate limit. …",
  "code": "API_KEY_RATE_LIMITED",
  "retryAfter": 7,
  "docsUrl": "https://polytrackers.com/docs/api"
}

Idempotency for /api/trade/execute

Trade execution is idempotent when you supply an Idempotency-Key header. For Agent API Key requests the header is required (400 IDEMPOTENCY_KEY_REQUIRED otherwise); session requests may still pass idempotencyKey in the body.

  • Accepted formats: UUIDv4 (preferred) or any 8–256 printable-ASCII token.

  • Retrying the same key within 24 hours replays the original trade result (200 with idempotencyReused: true) instead of re-executing.

  • Two concurrent requests with the same key return 409 TRADE_IN_FLIGHT for the loser:

    json
    {
      "error": "trade_in_flight",
      "code": "TRADE_IN_FLIGHT",
      "idempotencyKey": "agent-trade-2026-04-20-001",
      "retryAfter": 5
    }

Bot challenge (403)

Session traffic that BotID flags as automated receives:

json
{
  "error": "bot_challenge_failed",
  "reason": "automated_traffic_detected",
  "suggestedAction": "authenticate_with_api_key",
  "docsUrl": "https://polytrackers.com/docs/api"
}

Valid Authorization: Bearer ptk_… requests bypass BotID entirely — see llms.txt.


Quickstart (agent flow)

1) Sign up or log in

bash
curl -X POST "https://polytrackers.com/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@example.com","password":"strong-password"}'

Response includes:

  • access_token
  • refresh_token
  • token_type
  • expires_in

2) Read account + tier

bash
curl "https://polytrackers.com/api/account" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Returns tier (effective tier, honoring active trial), trialEndsAt, apiKeysCount, walletsCount, onboarding + wallet-link status.

3) Discover markets

bash
curl "https://polytrackers.com/api/markets?query=btc&status=open&sort=volume&limit=25"

4) Trigger anomaly scan (Pro/Elite)

bash
curl -X POST "https://polytrackers.com/api/scan/trigger" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

5) Read anomalies

Session or Agent API Key (signals:read):

bash
curl "https://polytrackers.com/api/anomalies?limit=50&severity=high" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Free-tier callers see at most 5 rows, within the last 7 days, and only those detected more than 1 hour ago.

6) Read anomaly detector performance

Aggregate win-rate, average return, and P&L for historical anomaly detections. Backed by the anomaly_performance_daily view.

bash
curl "https://polytrackers.com/api/anomalies/performance?since=2026-01-01T00:00:00Z&until=2026-04-01T00:00:00Z&group_by=month&anomaly_type=SHARP_MOVE" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Query parameters:

  • since, until — ISO-8601 datetimes. Defaults to the last 30 days; the window is capped at 365 days.
  • group_by — one of day (default), month, anomaly_type, severity, all.
  • anomaly_type, severity — optional filters passed straight through to the view.

Response body:

  • window{ since, until } echoing the resolved window (ISO-8601).
  • totals — aggregate { flagged, resolved, wins, losses, voids, winRate, avgReturnPct, totalPnlUsd, equalDollarPnlPer100 } across the window.
  • series — same shape as totals but keyed by cohort (the group_by bucket), sorted ascending.
  • coverageresolved / flagged for the window (0–1).
  • coverageThreshold — the minimum coverage at which headline numbers are considered reliable (currently 0.5).
  • headlineReliablecoverage >= coverageThreshold.

equalDollarPnlPer100 is a simulation: $100 flat-staked on every decided anomaly in the cohort, expressed as total dollars of P&L.

Accepts session auth (cookie/JWT) or an Agent API Key with signals:read scope. Responses are cached privately with s-maxage=60, stale-while-revalidate=300.

7) Read unified trade history

bash
curl "https://polytrackers.com/api/trades?type=all&status=all&sort=newest&limit=25&offset=0" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response body includes tier and historyDepthDays (7 for free, 90 for pro, null for elite).

8) Readiness-gated real trade execution

Session auth requires the real-automation beta gate plus trading readiness: Polymarket trading credentials, trading wallet/signing setup, wallet risk config, circuit-breaker state, idempotency, reservations, and audit logging.

Session auth:

bash
curl -X POST "https://polytrackers.com/api/trade/execute" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "conditionId":"0xconditionid",
    "side":"YES",
    "amount":20,
    "limitPrice":0.5,
    "idempotencyKey":"agent-trade-2026-04-16-001"
  }'

Agent API Key with trade:execute scope:

bash
curl -X POST "https://polytrackers.com/api/trade/execute" \
  -H "Authorization: Bearer $AGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"conditionId":"0x...","side":"YES","amount":20,"idempotencyKey":"..."}'

Agent API Key lifecycle

Generate Agent API Key (JWT bearer only)

Pro callers may request signals:read, the narrow trade:execute scope, and the narrow agent:scan scope; Elite callers may additionally request agent:full. Accounts can keep 2 active Agent API Keys so you can rotate by generating a new key, updating clients and agents, then revoking the old key (409 API_KEY_LIMIT_REACHED when the cap is reached).

bash
curl -X POST "https://polytrackers.com/api/keys/generate" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"nickname":"Agent API Key","expiresInDays":90,"scopes":["signals:read"]}'
  • expiresInDays: 1–365, defaults to 90.
  • scopes: defaults to ["signals:read"]. Add trade:execute only when intentionally creating a real-trading key. Pro-tier requests for agent:full are stripped, while trade:execute and agent:scan are allowed where their automation surfaces are enabled.
  • The raw api_key is returned once in the response — store it securely.

List keys

bash
curl "https://polytrackers.com/api/keys" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Use Agent API Key for public whale feed (Elite)

bash
curl "https://polytrackers.com/api/public/whale-signals?limit=25" \
  -H "Authorization: Bearer $AGENT_API_KEY"

Outbound webhooks (Pro/Elite)

Create, list, delete, and test delivery endpoints live under /api/webhooks*:

  • GET /api/webhooks — list your registrations.
  • POST /api/webhooks — register a new URL with optional filters (minScore, severity[], anomalyTypes[], marketCategories[]) and a secret. Capped at 5 (Pro) / 50 (Elite); over-limit returns WEBHOOK_LIMIT_REACHED.
  • DELETE /api/webhooks/{id} — soft-delete a registration. The row is retained for audit (with deleted_at stamped and status=paused), it will stop receiving future deliveries, and historical delivery_log entries remain queryable.
  • GET /api/webhooks/{id}/deliveries — recent delivery logs.
  • POST /api/webhooks/{id}/test — fire a test payload.

Delivered payloads are signed with the registration's secret; verify x-polytrackers-signature against sha256=HMAC_SHA256(raw_body, secret).


Deletion & audit retention

PolyTrackers favors soft deletion for user-owned resources so that reporting, billing, copy-trading analytics, and security audits remain reliable. The behavior per-resource is:

ResourceEndpoint(s)Behavior
Agent API KeysDELETE /api/keys?id=…Soft-revoke: is_active=false, revoked_at=now(). Authentication is rejected immediately; row is retained for audit.
Mock walletsDELETE /api/wallets, DELETE /api/mock/wallet/{id}Soft-delete: is_active=false, deleted_at=now(). Whale assignments are detached (active=false, removed_at=now()). mock_trades, whale_activity, and whale_decision_traces are preserved. Wallet names can be reused.
Mock trades (single)DELETE /api/mock/delete-trade?tradeId=…Only open trades may be deleted. Attempts to delete resolved/closed trades return 422 CANNOT_DELETE_RESOLVED_TRADE.
Mock trades (bulk)DELETE /api/mock/delete-trade (body { type })Only type: "open" is accepted for bulk deletes, and only open trades are removed. Any other type is rejected with 400.
Outbound webhook registrationsDELETE /api/webhooks/{id}Soft-delete: deleted_at=now(), status=paused. No future deliveries fire; historical delivery_log remains queryable via GET /api/webhooks/{id}/deliveries.
Alert preferencesDELETE /api/alerts/preferencesHard reset of the preferences row.
Roster (whale) assignmentsDELETE /api/roster/{walletId}Detach: row retained, active=false, removed_at=now().
Trade ordersDELETE /api/trade/orders/{id}Cancels the live order at the CLOB; hard-removes the queued row.

Closed/resolved mock trades are never user-deletable by design — they feed the leaderboard, copy-trading scoring, and tier-history analytics. Single-trade delete attempts on resolved trades return 422 CANNOT_DELETE_RESOLVED_TRADE, and the database RPCs (delete_mock_trade_atomic, bulk_delete_mock_trades_atomic) raise cannot_delete_resolved_trade (SQLSTATE P0101) as a defense in depth.


Whale service + inbound webhooks

Existing whale-service endpoints remain supported and documented in OpenAPI:

  • Wallet/roster management (/api/wallets, /api/roster*)
  • Service status/config/control (/api/whale/*)
  • Webhook ingest/events/replay (/api/whale/webhook*)

For replay automation, use dryRun: true first, then replay live once validated.


MCP server

PolyTrackers exposes a stateless MCP endpoint for agent clients:

  • GET /api/mcp — unauthenticated health/capability probe.
  • POST /api/mcp — JSON-RPC 2.0 over Streamable HTTP. Send Authorization: Bearer <agent-api-key> — use the same ptk_... key as your REST/API examples.
  • GET /api/mcp/events — optional SSE notifications for anomalies, whale_signals, copy_signals, and scan_progress, with : keepalive every 15s.

Clients that only support stdio should use @polytrackers/mcp-stdio; see docs/features/mcp/client-setup.md.

Scopes:

  • signals:read — read-only tool/resource catalog for Pro+.
  • trade:execute — permits pt_trade_execute for Pro+ after pt_trade_preflight approval.
  • agent:scan — permits pt_scan_trigger for Pro+ without granting broader writes.
  • agent:full — current Elite write/execution superset.

Reliability notes

  • Handle 429 on all rate-limited endpoints and respect Retry-After.
  • Treat trade execution as idempotent when you provide idempotencyKey (idempotent replays return 200 with idempotencyReused: true).
  • POST /api/keys/generate returns the raw key once — store it securely. Keep at most two active Agent API Keys; rotate by generating a new key, updating clients/agents, then revoking the old key.
  • /api/anomalies/{id} may return 404 when a record falls outside your tier window.
  • TIER_UPGRADE_REQUIRED responses include requiredTier, currentTier, and upgradeUrl — surface these to the user/agent verbatim.