Generate your Agent API Key
Free users can generate a read-only Agent API Key for MCP tools with signals:read and 200 MCP requests/day. Pro adds real-trade REST/MCP scopes; Elite adds full agent write access.
PolyTrackers API (External + AI Agent Guide)
This is the production-facing API guide for external developers and AI agents.
- OpenAPI JSON:
/openapi.json - Agent instructions:
/llms.txtand/skill.md - MCP endpoint:
https://polytrackers.com/api/mcp
Scope
This guide/spec covers the full AI agent surface:
- Auth:
/api/auth/refresh - Account/Tier:
/api/account,/api/account/stats,/api/account/risk-profile - Discovery:
/api/markets,/api/market-signals,/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 dataagent:scan— scan trigger where allowedtrade:execute— real trade execution only, after readiness and preflight gates passagent:full— full agent/write/trade access (currently Elite-only for Agent API Keys)
Endpoints that accept Agent API Keys:
| Endpoint | Required scope |
|---|---|
GET /api/anomalies | signals:read |
GET /api/public/whale-signals | signals:read |
GET /api/public/copy-signals | signals:read |
POST /api/trade/execute | trade:execute |
GET /api/trade/history | agent:full |
GET/POST/DELETE /api/trade/orders* | agent:full |
4) Service auth
For whale-service control endpoints:
x-whale-service-secret: <secret>orAuthorization: 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)./api/keys+POST /api/keys/generate: allowed; generated keys always get exactlysignals:read(requested write/automation scopes are stripped). Limit: 1 active Agent API Key per user; rotate by revoking the old key, then generating a replacement. MCP usage is capped at 10 requests/min per tool and 200 requests/day total.POST /api/trade/execute: session callers can execute only when manual trading-readiness checks pass. Agent API Key/MCP execution is unavailable because Free keys never carrytrade:execute./api/trade/historyand order listing/detail routes: not allowed (403).DELETE /api/trade/orders/{id}may cancel the signed-in user's own resting order because cancellation reduces exposure./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=realrejected with403).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 tosignals:read, with optionaltrade:executefor real trade execution andagent:scanfor scan automation where allowed. Limit: 1 active Agent API Key per user; rotate by revoking the old key, then generating a replacement./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 manual trading-readiness checks pass. Agent API Key/MCP execution requirestrade:executescope./api/trade/historyand order listing/detail routes: not allowed.DELETE /api/trade/orders/{id}may cancel the signed-in user's own resting order.
Elite
- Full
GET /api/tradesaccess (type=realallowed); 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 includesignals:read,trade:execute,agent:scan, and/oragent:full. Limit: 1 active Agent API Key per user; rotate by revoking the old key, then generating a replacement./api/trade/execute,/api/trade/history, and/api/trade/orders*: allowed where the route-specific readiness checks pass (trade:executeoragent:fullfor execute API-key auth). Browser/session order cancellation is allowed for the signed-in user's own resting order regardless of tier./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.
| Endpoint | Limit | Scope |
|---|---|---|
POST /api/auth/* | 10/minute | IP |
POST /api/scan/trigger | Pro: 2/hour, Elite: 10/hour | user |
POST /api/keys/generate | 5/hour per user | user |
POST /api/trade/execute | 10/minute per user + 20/minute per API key | user + key |
GET /api/public/whale-signals | 120/minute per API key | API key |
GET /api/public/copy-signals | 120/minute per API key | API key |
429 response shape
Every 429 body includes "error" (string). The Retry-After header (seconds)
is the authoritative back-off signal — it is present on all rate-limited
responses (the one exception: 429s proxied from the upstream auth provider on
POST /api/auth/refresh may omit it). Other body fields vary by endpoint, so
treat them as optional:
| Endpoint / limiter | 429 body |
|---|---|
GET /api/public/whale-signals | { error } |
GET /api/public/copy-signals | { error } |
POST /api/trade/execute (per API key) | { error, code: "API_KEY_RATE_LIMITED", retryAfter, docsUrl } |
POST /api/trade/execute (per user) | { error, code: "RATE_LIMITED" } |
POST /api/keys/generate | { error, code: "RATE_LIMITED" } |
POST /api/auth/refresh | { error, code: "RATE_LIMITED" } |
POST /api/scan/trigger | { error } |
The fullest shape — returned by the /api/trade/execute per-API-key limiter:
{
"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.
Every /api/trade/execute body must also include regionCertification: true
to certify the caller is permitted to trade in their jurisdiction and is not in
a restricted or prohibited Polymarket trading region.
-
Accepted formats: UUIDv4 (preferred) or any 8–256 printable-ASCII token.
-
Retrying the same key within 24 hours replays the original trade result (
200withidempotencyReused: true) instead of re-executing. -
Two concurrent requests with the same key return
409 TRADE_IN_FLIGHTfor the loser:json{ "error": "trade_in_flight", "code": "TRADE_IN_FLIGHT", "idempotencyKey": "agent-trade-2026-04-20-001", "retryAfter": 5 }
Lifecycle contradictions and order-book indicators
Agent API and MCP clients must treat Gamma lifecycle fields as conservative
write gates. When pt_mock_price_get or a composed market-intel/copy-desk
workflow reports PAST_END_DATE_BUT_MARKET_APPEARS_LIVE, that is contradiction
evidence only; it is not permission to place, mirror, or override by default.
Live CLOB/order-book indicators, bid/ask/spread rows, recent trades, or
enableOrderBook signals do not override MARKET_PAST_END_DATE,
MARKET_CLOSED, auth, tier, anti-IDOR, preflight/idempotency, wallet-readiness,
region, or real-money execution safeguards.
A future manual/gated exception must prove the Gamma lifecycle field is stale, require explicit user/operator approval for the exact action, write an audit log, and must not broaden default Agent API/MCP write privileges.
Bot challenge (403)
Session traffic that BotID flags as automated receives:
{
"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 in and obtain a session
PolyTrackers auth is passwordless. Create an account or sign in through the web
app at /register or
/login using Google OAuth or an emailed
magic link (Terms of Service and Privacy Policy acceptance is captured during
sign-up). This yields a Supabase session — a session cookie plus an
access_token / refresh_token pair you can pass as a bearer token.
Exchange a refresh token for a fresh session pair when the access token nears expiry:
curl -X POST "https://polytrackers.com/api/auth/refresh" \
-H "Content-Type: application/json" \
-d '{"refresh_token":"'"$REFRESH_TOKEN"'"}'Response includes:
access_tokenrefresh_tokentoken_typeexpires_in
2) Read account + tier
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
curl "https://polytrackers.com/api/markets?query=btc&status=open&sort=volume&limit=25"To decorate public market cards with coarse recent signal evidence, pass up to 100 comma-separated condition IDs. The response contains only 24-hour whale and anomaly booleans—no wallet, trade-size, price, or execution data:
curl "https://polytrackers.com/api/market-signals?conditionIds=0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"4) Trigger anomaly scan (Pro/Elite)
curl -X POST "https://polytrackers.com/api/scan/trigger" \
-H "Authorization: Bearer $ACCESS_TOKEN"5) Read anomalies
Session or Agent API Key (signals:read):
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.
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 ofday(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 astotalsbut keyed bycohort(the group_by bucket), sorted ascending.coverage—resolved / flaggedfor the window (0–1).coverageThreshold— the coverage at which the cohort is considered mature enough to surface headline numbers (currently0.5).minDecidedForHeadline— the absolute number of decided outcomes (wins + losses) that is, on its own, enough to surface headline numbers (currently20).headlineReliable—coverage >= coverageThreshold || (wins + losses) >= minDecidedForHeadline. Because markets resolve long after detection, a window can have low coverage while still holding a large, meaningful sample of decided outcomes; either condition makes the win rate reliable.
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
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 manual trading readiness: trading wallet/signing setup, wallet funding, wallet risk config, circuit-breaker state, idempotency, reservations, region certification, and audit logging.
Session auth:
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",
"regionCertification":true
}'Agent API Key with trade:execute scope:
curl -X POST "https://polytrackers.com/api/trade/execute" \
-H "Authorization: Bearer $AGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c2b7f9e-47b8-4ad2-95b5-8f8d5f2f6a3c" \
-d '{"conditionId":"0x...","side":"YES","amount":20,"regionCertification":true}'CDP delegated-wallet browser users must submit explicit limit orders until the SDK adapter supports cap-priced immediate-or-cancel market orders. Non-CDP market buys retain the server-side slippage-cap path.
9) Cancel an own resting real order
Session callers can cancel their own resting order even when their tier cannot list all CLOB orders:
curl -X DELETE "https://polytrackers.com/api/trade/orders/$ORDER_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"MCP/Agent API Key order tools still require agent:full.
Agent API Key lifecycle
Generate Agent API Key (JWT bearer only)
Free callers can generate read-only Agent API Keys for MCP access; requested scopes are reduced to signals:read and MCP usage is capped at 200 requests/day. 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 keep 1 active Agent API Key; rotate by revoking the old key, then generating a replacement and updating clients and agents (409 API_KEY_LIMIT_REACHED when the cap is reached).
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"]. Free keys are always reduced tosignals:read; paid-tier validation still applies outside the free MCP/read surface. Addtrade:executeonly when intentionally creating a real-trading key. Pro-tier requests foragent:fullare stripped, whiletrade:executeandagent:scanare allowed where their automation surfaces are enabled.- The raw
api_keyis returned once in the response — store it securely.
List keys
curl "https://polytrackers.com/api/keys" \
-H "Authorization: Bearer $ACCESS_TOKEN"Use Agent API Key for public whale feed (Elite)
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 returnsWEBHOOK_LIMIT_REACHED.DELETE /api/webhooks/{id}— soft-delete a registration. The row is retained for audit (withdeleted_atstamped andstatus=paused), it will stop receiving future deliveries, and historicaldelivery_logentries 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:
| Resource | Endpoint(s) | Behavior |
|---|---|---|
| Agent API Keys | DELETE /api/keys?id=… | Soft-revoke: is_active=false, revoked_at=now(). Authentication is rejected immediately; row is retained for audit. |
| Mock wallets | DELETE /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. |
| Outbound webhook registrations | DELETE /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 preferences | DELETE /api/alerts/preferences | Hard reset of the preferences row. |
| Roster (whale) assignments | DELETE /api/roster/{walletId} | Detach: row retained, active=false, removed_at=now(). |
| Trade orders | DELETE /api/trade/orders/{id} | Cancels the live order at the CLOB; hard-removes the queued row. |
Mock trades are not user-deletable by design once placed — open, closed, and
resolved rows feed the leaderboard, copy-trading scoring, and tier-history
analytics. To exit an open mock position, close it through
POST /api/mock/resolve; this records the terminal state and preserves the
trade row for history.
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. SendAuthorization: Bearer <agent-api-key>— use the sameptk_...key as your REST/API examples.GET /api/mcp/events— optional SSE notifications foranomalies,whale_signals,copy_signals, andscan_progress, with: keepaliveevery 15s.
During gated launch, MCP setup is Streamable HTTP only. Point any MCP client at
https://polytrackers.com/api/mcp with Authorization: Bearer <agent-api-key>.
For stdio-only MCP hosts, the @polytrackers/mcp-stdio bridge relays stdio
JSON-RPC to that endpoint. It reads POLYTRACKERS_API_KEY (required),
POLYTRACKERS_MCP_URL (optional, defaults to the endpoint above),
POLYTRACKERS_MCP_ALLOWED_HOSTS (optional host allowlist), and
POLYTRACKERS_MCP_TIMEOUT_MS (optional). Full hosted and stdio setup examples
are published in /skill.md.
To test strategies programmatically with no real money — the mock (paper) trading tool flow, free-tier reads, and going-live fees — see the Polymarket Mock Trading API guide.
Agent skill distribution
Install the PolyTrackers agent skill (which bundles this MCP setup) with one
command: npx skills add polytrackers/polymarket-copy-trading-skill. Official
distribution channels:
| Channel | Location |
|---|---|
| GitHub | polytrackers/polymarket-copy-trading-skill |
| skills.sh | polytrackers/polymarket-copy-trading-skill |
| npm | @polytrackers/mcp-stdio (stdio bridge) |
Scopes:
signals:read— read-only tool/resource catalog for Free+; free keys are shaped by 7-day history, top-5 delayed anomalies, and the 200 requests/day MCP quota.trade:execute— permitspt_trade_executefor Pro+ afterpt_trade_preflightapproval.agent:scan— permitspt_scan_triggerfor Pro+ without granting broader writes.agent:full— current Elite write/execution superset.
Reliability notes
- Handle
429on all rate-limited endpoints and respectRetry-After. - Treat trade execution as idempotent when you provide
idempotencyKey(idempotent replays return200withidempotencyReused: true). POST /api/keys/generatereturns the raw key once — store it securely. Each account keeps one active Agent API Key; rotate by revoking the old key, then generating a replacement and updating clients/agents./api/anomalies/{id}may return404when a record falls outside your tier window.TIER_UPGRADE_REQUIREDresponses includerequiredTier,currentTier, andupgradeUrl— surface these to the user/agent verbatim.

