REST API Stable v1.0 <80ms avg

API Reference

Programmatic access to the full PolyCopyBot platform. Manage your bot, query wallets, stream live positions and build your own copy-trading stack — all via a clean REST interface.

Base URL https://api.polycopybot.app/v1
Overview Auth Rate Limits Errors Wallets Bot Orders Portfolio Subscription WebSocket SDKs Changelog
Overview

The PolyCopyBot REST API gives you full programmatic control over the platform. All endpoints return JSON, accept JSON request bodies, and authenticate via a Bearer token in the Authorization header.

Sub-80ms

Average API response time globally via edge caching.

TLS 1.3

All connections are encrypted. HTTP requests are redirected.

Versioned

Current stable version is v1. Legacy versions kept for 12 months.

JSON Only

All responses are application/json with consistent envelope format.

Every response is wrapped in a standard envelope: { "success": true, "data": {...}, "meta": {...} }. On error: { "success": false, "error": { "code": "...", "message": "..." } }.
Authentication

PolyCopyBot uses Bearer token authentication. Generate your API key from the Dashboard → Settings → API Keys tab. Include it in every request header.

YOUR API KEY pcb_live_sk_4a7f3c9e2b1d8f6a0e5c3b7d9f2a4e6c hover to reveal
# Pass your API key as a Bearer token in the Authorization header
curl -X GET "https://api.polycopybot.app/v1/wallets" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
const API_KEY = 'YOUR_API_KEY';

const res = await fetch('https://api.polycopybot.app/v1/wallets', {
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type':  'application/json'
  }
});
const data = await res.json();
console.log(data);
import requests

API_KEY = "YOUR_API_KEY"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type":  "application/json"
}

response = requests.get(
    "https://api.polycopybot.app/v1/wallets",
    headers=headers
)
data = response.json()
print(data)
<?php
$apiKey = 'YOUR_API_KEY';

$ch = curl_init('https://api.polycopybot.app/v1/wallets');
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer {$apiKey}",
        'Content-Type: application/json'
    ],
    CURLOPT_RETURNTRANSFER => true
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
Keep your API key secret. Never expose it in client-side code or public repositories. Rotate it immediately from the dashboard if compromised.
Rate Limits

Requests are throttled per API key per plan. Exceeding the limit returns HTTP 429 Too Many Requests with a Retry-After header indicating seconds to wait.

Free
60
requests / minute
Starter
300
requests / minute
Pro
1,000
requests / minute
Enterprise
Unlimited
custom SLA

Rate limit headers are returned with every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (Unix timestamp).

Errors

PolyCopyBot uses conventional HTTP response codes. Errors include a machine-readable code string and a human-readable message.

HTTP CodeMeaningDescription
200OKRequest succeeded. Data in data field.
400Bad RequestMissing or invalid parameters. Check error.fields for field-level detail.
401UnauthorizedMissing, invalid or expired API key.
403ForbiddenValid key but insufficient plan permissions for this endpoint.
404Not FoundResource doesn't exist or doesn't belong to your account.
429Too Many RequestsRate limit exceeded. Respect Retry-After header.
500Server ErrorUnexpected server-side issue. Automatically logged; retries are safe.
401 UnauthorizedError envelope
{ "success": false, "error": { "code": "INVALID_API_KEY", "message": "The provided API key is invalid or has been revoked." } }
Wallet API

Query the PolyCopyBot-tracked wallet database. Filter by score, ROI, win-rate and more. Used internally by the dashboard leaderboard.

GET /v1/wallets List tracked wallets

Returns a paginated list of wallets tracked by the PolyCopyBot scoring engine. Sorted by AI score descending by default.

Query Parameters

ParameterTypeRequiredDescription
pageintegeroptionalPage number, default 1.
limitintegeroptionalResults per page, 1–100, default 20.
sortstringoptionalscore | roi_7d | roi_30d | win_rate. Default: score.
min_scorenumberoptionalFilter wallets with AI score ≥ this value (0–100).
networkstringoptionalpolygon | ethereum | arbitrum | bnb. Omit for all.
200 OKapplication/json
{ "success": true, "data": [ { "address": "0x19d9314b7d2175ba292a5e58158bf5e92ca6a93c", "label": "Whale #1", "score": 94.7, "roi_7d": 18.4, "roi_30d": 61.2, "win_rate": 78.3, "trades": 312, "network": "polygon" } ], "meta": { "page": 1, "limit": 20, "total": 1428 } }
GET /v1/wallets/{address} Get single wallet

Retrieve full details for a specific wallet address including score breakdown, recent trade history and market exposure.

Path Parameters

ParameterTypeRequiredDescription
addressstringrequiredEthereum-compatible wallet address (0x…).
200 OKapplication/json
{ "success": true, "data": { "address": "0x19d9314b7d2175ba292a5e58158bf5e92ca6a93c", "label": "Whale #1", "score": 94.7, "score_factors": { "consistency": 96, "volume": 88, "timing": 91, "diversity": 78 }, "roi_7d": 18.4, "roi_30d": 61.2, "roi_90d": 142.8, "win_rate": 78.3, "total_trades": 312, "avg_hold_hours": 14.6, "network": "polygon", "first_seen": "2024-08-03T11:22:00Z", "last_active": "2025-04-14T18:40:00Z" } }
GET /v1/wallets/{address}/positions Active positions

Returns all currently open positions for a tracked wallet. Useful for real-time market exposure analysis.

200 OK
{ "success": true, "data": [ { "market_id": "0xabc123", "market_title": "Will BTC hit $100k by May 2025?", "outcome": "Yes", "size_usdc": 420.00, "avg_price": 0.63, "current_price":0.71, "unrealised_pnl":53.33, "opened_at": "2025-03-28T09:14:00Z" } ] }
GET /v1/wallets/{address}/stats Historical stats

Daily OHLC-style portfolio data for charts. Returns up to 365 daily data points.

ParameterTypeRequiredDescription
periodstringoptional7d | 30d | 90d | 365d. Default: 30d.
Bot API

Start, stop and configure your copy-trading bot programmatically. Bot endpoints require an active subscription.

All Bot API endpoints require a Pro or higher plan. Calling them with a Free key returns 403 Forbidden.
GET /v1/bot/status Get current bot state
200 OK
{ "success": true, "data": { "running": true, "started_at": "2025-04-14T08:00:00Z", "uptime_seconds": 38400, "network": "polygon", "tracked_wallets":5, "open_positions": 3, "total_trades_today":12, "pnl_today": +47.83 } }
POST /v1/bot/start Start the bot

Activates the bot using current saved settings. No request body required. Returns error if bot is already running or private key is not configured.

curl -X POST "https://api.polycopybot.app/v1/bot/start" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch('https://api.polycopybot.app/v1/bot/start', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const data = await res.json();
response = requests.post(
    "https://api.polycopybot.app/v1/bot/start",
    headers=headers
)
200 OK
{ "success": true, "data": { "running": true, "started_at": "2025-04-15T10:30:00Z" } }
POST /v1/bot/stop Stop the bot

Gracefully stops the bot. Open positions are not automatically closed; they remain until manually resolved or the bot restarts.

200 OK
{ "success": true, "data": { "running": false, "stopped_at": "2025-04-15T12:00:00Z" } }
GET /v1/bot/settings Retrieve settings
200 OK
{ "success": true, "data": { "network": "polygon", "max_position_usdc": 500, "stop_loss_pct": 15, "take_profit_pct": 40, "min_wallet_score": 75, "max_open_positions":5, "copy_delay_ms": 250 } }
PUT /v1/bot/settings Update settings

Partial update supported — only send the fields you want to change. Settings take effect on the next bot action (or immediately if bot is running).

FieldTypeRequiredDescription
networkstringoptionalpolygon | ethereum | arbitrum | bnb
max_position_usdcnumberoptionalMax USDC per single position. Min: 10.
stop_loss_pctnumberoptionalStop-loss threshold, 1–100.
take_profit_pctnumberoptionalTake-profit threshold, 1–100.
min_wallet_scorenumberoptionalMinimum AI wallet score to copy, 0–100.
max_open_positionsintegeroptionalConcurrent open positions cap, 1–50.
curl -X PUT "https://api.polycopybot.app/v1/bot/settings" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stop_loss_pct": 20, "take_profit_pct": 50}'
const res = await fetch('https://api.polycopybot.app/v1/bot/settings', {
  method:  'PUT',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
  body:    JSON.stringify({ stop_loss_pct: 20, take_profit_pct: 50 })
});
response = requests.put(
    "https://api.polycopybot.app/v1/bot/settings",
    headers=headers,
    json={"stop_loss_pct": 20, "take_profit_pct": 50}
)
$payload = json_encode(['stop_loss_pct' => 20, 'take_profit_pct' => 50]);
$ch = curl_init('https://api.polycopybot.app/v1/bot/settings');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_POSTFIELDS     => $payload,
    CURLOPT_HTTPHEADER     => ["Authorization: Bearer {$apiKey}", 'Content-Type: application/json'],
    CURLOPT_RETURNTRANSFER => true
]);
Orders API

Inspect and manage orders placed by your bot. Orders represent individual copy trades executed on Polymarket.

GET /v1/orders List bot orders
ParameterTypeRequiredDescription
statusstringoptionalopen | filled | cancelled | all. Default: all.
fromstringoptionalISO 8601 date filter start, e.g. 2025-04-01.
tostringoptionalISO 8601 date filter end.
limitintegeroptionalMax results, 1–100, default 20.
200 OK
{ "success": true, "data": [ { "id": "ord_9f3a2c1e", "market_id": "0xabc123", "outcome": "Yes", "size_usdc": 250.00, "price": 0.63, "status": "filled", "copied_from": "0x19d9314b...", "created_at": "2025-04-10T14:22:00Z", "filled_at": "2025-04-10T14:22:00Z" } ] }
GET /v1/orders/{id} Get single order

Returns full detail for a single order including execution price, gas used and PnL if closed.

DELETE /v1/orders/{id} Cancel open order

Cancels an order that is in open state. Returns 400 if the order is already filled or cancelled.

Cancellation is irreversible. Partially filled orders cannot be cancelled — only fully open orders.
200 OK
{ "success": true, "data": { "id": "ord_9f3a2c1e", "status": "cancelled" } }
Portfolio API

Aggregate view of your copy-trading account: balances, PnL, performance over time.

GET /v1/portfolio Portfolio summary
200 OK
{ "success": true, "data": { "balance_usdc": 4820.55, "invested_usdc": 1350.00, "unrealised_pnl": +312.40, "realised_pnl": +820.55, "total_pnl": +1132.95, "roi_pct": +30.7, "open_positions": 3, "total_trades": 148, "win_rate": 71.6 } }
GET /v1/portfolio/history Daily equity curve

Daily snapshots of portfolio value. Useful for rendering equity curves. Returns up to 365 data points.

ParameterTypeRequiredDescription
periodstringoptional7d | 30d | 90d | 365d. Default 30d.
Subscription

Retrieve active plan details, limits and expiry for the authenticated API key's account.

GET /v1/subscription Current plan
200 OK
{ "success": true, "data": { "plan": "pro", "status": "active", "expires_at": "2025-05-15T00:00:00Z", "api_rate_limit":1000, "features": [ "bot_control", "portfolio_api", "websocket", "webhook" ] } }
WebSocket API

Stream real-time events from your bot and the wallet tracker. The WebSocket endpoint is available on Pro and Enterprise plans.

WebSocket URL: wss://ws.polycopybot.app/v1?token=YOUR_API_KEY — authenticate via query param on initial connection.

Subscribe to channels

const ws = new WebSocket('wss://ws.polycopybot.app/v1?token=YOUR_API_KEY');

ws.onopen = () => {
  // Subscribe to bot events and live wallet feed
  ws.send(JSON.stringify({
    type:     'subscribe',
    channels: ['bot.events', 'wallet.trades']
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg.type, msg.data);
};
import asyncio, websockets, json

async def main():
    url = "wss://ws.polycopybot.app/v1?token=YOUR_API_KEY"
    async with websockets.connect(url) as ws:
        await ws.send(json.dumps({
            "type": "subscribe",
            "channels": ["bot.events", "wallet.trades"]
        }))
        async for msg in ws:
            print(json.loads(msg))

asyncio.run(main())

Available Channels

bot.events
Bot start/stop, setting changes, errors and health pings.
bot.orders
Fired every time your bot places, fills or cancels an order.
wallet.trades
Live trade stream from all wallets your bot is currently copying.
portfolio.updates
Real-time PnL updates as positions are opened and closed.
SDKs & Libraries

Official client libraries to get started faster. Community SDKs welcome — open a PR on GitHub.

Quick install

npm install @polycopybot/sdk
pip install polycopybot
composer require polycopybot/sdk
Changelog

API version history and release notes. Breaking changes are announced 30 days in advance.

Apr 2025
v1.4.0
  • NEWWebSocket portfolio.updates channel added
  • NEWGET /v1/wallets/{address}/stats endpoint
  • IMPRate limit headers now included on all responses
  • FIXEdge case where roi_90d returned null for new wallets
Feb 2025
v1.3.0
  • NEWDELETE /v1/orders/{id} — cancel open orders via API
  • NEWnetwork filter on GET /v1/wallets
  • IMPResponse times improved by 22% via edge caching
Dec 2024
v1.2.0
  • NEWPortfolio history endpoint with daily equity curve data
  • NEWSDK packages for JavaScript and Python
  • FIXPagination meta returning incorrect total count
Oct 2024
v1.0.0 — GA
  • NEWREST API public launch — Wallets, Bot, Orders, Portfolio
  • NEWWebSocket streams for real-time event delivery
  • NEWBearer token authentication with per-plan rate limits