⭐ Your watchlist
Open positions
| Market | Side | Qty | Avg cost | Mark | Value | Unrealized |
|---|
| Time | Market | Outcome | Side | Type | Qty | Filled | Avg px | Slippage | Status |
|---|
Trading agents
Deploy automated bots against the same live paper-trading
engine. Each agent gets an API key — pass
Authorization: Bearer <key> on REST calls or
?key=<key> on the WebSocket.
Top traders
| Rank | Trader | Equity | Total P&L |
|---|
Papermarket API
A clean REST + WebSocket API to run automated trading bots against real, live Polymarket & Kalshi odds with simulated money — realistic fills, full historical data. Alpaca for betting bots.
Overview
All endpoints live under /api (the alias
/v1 also works). Responses are JSON.
- Money fields are integer US cents (e.g.
equity_cents). - Prices are YES probabilities in
[0,1]; a share pays $1 if it resolves your way. NO price =1 − YES. - Every account starts with $10,000 virtual cash. Free, unlimited paper trading.
- Send a unique
client_idon orders for idempotent retries.
Authentication
Create an API key under Profile → Agents → Deploy agent (open Agents), then send it as a bearer token on every request:
Quickstart (Python)
Authenticate, find a market, and place your first order:
Or with curl:
Account & portfolio
Orders
Positions & fills
Markets & events
Order books
Historical data
Top-of-book quotes and full order-book snapshots are recorded from day one — the dataset you backtest against. JSON or CSV.
Recorded coverage
Live count of markets with recorded history (most active first).
| Venue | Market | Samples | First | Last | Download |
|---|
Backtesting
Replay recorded order-book history through a strategy using the
same fill engine as live — orders walk the real book
for slippage and partial fills and execute against the book recorded
after your latency, so results track live trading. The
response returns performance metrics, an equity curve and the full
trade log (P&L reconciles exactly: total = realized + unrealized).
WebSocket
Stream live quotes and your own order/fill events. Authenticate with
?key=pk_live_... to also receive private order events.
| Send | Effect |
|---|---|
{"action":"subscribe","markets":"all"} | Stream every market's quotes |
{"action":"subscribe","markets":["SIM:..","POLY:.."]} | Stream specific markets |
{"action":"unsubscribe","markets":[..]} | Stop streaming those markets |
Server pushes {"type":"quotes","data":[…]} and, when authenticated,
{"type":"order_update","order":{…}}.
Errors & rate limits
Errors return an HTTP status with {"detail": "message"}
(validation errors return a list of field messages).
| Status | Meaning |
|---|---|
| 400 | Bad request |
| 401 | Missing/invalid API key or session |
| 404 | Not found (unknown market / order) |
| 409 | Conflict (e.g. email already registered) |
| 422 | Validation error (bad field) |
| 429 | Rate limit exceeded |
Rate limit: 600 requests/minute per API key or IP. Every
/api response carries X-RateLimit-Limit and
X-RateLimit-Remaining; a 429 includes
Retry-After.
Note: an order with insufficient funds/inventory is not an
HTTP error — it returns 200 with status:"rejected" and a
reject_reason (and partial fills set status:"partial").
Interactive docs & SDK
- Swagger UI — try every endpoint in the browser (click Authorize, paste your key).
- ReDoc — clean reference.
- OpenAPI JSON — generate a client in any language.
examples/bot_example.pyin the repo — a runnable streaming bot.
Comments