Developers
Build bots and tools against the Predictly API: the same REST and WebSocket endpoints the website uses. Prices are integer cents (1–99), YES + NO = 100, and balances are integer US cents ($1 = 100).
Open interactive API docsAuthentication
- Create a key on this page and save the private key (.pem).
- For each request, sign
timestamp + METHOD + pathwith Ed25519. Use the timestamp in unix milliseconds and the path without its query string. - Send
FS-ACCESS-KEY,FS-ACCESS-TIMESTAMPandFS-ACCESS-SIGNATURE(base64). Timestamps must be within 30 seconds of server time.
# pip install requests cryptography
import base64, time, requests
from cryptography.hazmat.primitives import serialization
API = "http://localhost:3000/api"
KEY_ID = "your-api-key-id"
private_key = serialization.load_pem_private_key(open("foresight.pem", "rb").read(), password=None)
def signed(method: str, path: str) -> dict:
ts = str(int(time.time() * 1000))
message = (ts + method.upper() + path.split("?")[0]).encode()
return {
"FS-ACCESS-KEY": KEY_ID,
"FS-ACCESS-TIMESTAMP": ts,
"FS-ACCESS-SIGNATURE": base64.b64encode(private_key.sign(message)).decode(),
}
print(requests.get(f"{API}/v1/portfolio/balance", headers=signed("GET", "/v1/portfolio/balance")).json())
# Buy 5 YES at up to 40¢ (limit order, rests if not filled)
order = {"ticker": "FEDDEC-26DEC-HOLD", "side": "yes", "action": "buy", "type": "limit", "count": 5, "price": 40}
r = requests.post(f"{API}/v1/portfolio/orders", json=order, headers=signed("POST", "/v1/portfolio/orders"))
print(r.status_code, r.json())Real-time WebSocket
const ws = new WebSocket("ws://localhost:3000/api/v1/ws");
ws.onopen = () =>
ws.send(JSON.stringify({
id: 1,
cmd: "subscribe",
params: { channels: ["orderbook_delta", "ticker", "trade"], market_tickers: ["FEDDEC-26DEC-HOLD"] },
}));
// Frames: { type, sid, seq, msg }. orderbook_delta starts with an orderbook_snapshot.
// seq increases by 1 per subscription. On a gap, unsubscribe + resubscribe for a fresh snapshot.
ws.onmessage = (e) => console.log(JSON.parse(e.data));Public channels: orderbook_delta, orderbook_snapshot, ticker, trade, market_status. Private channels (logged-in session or signed upgrade request): fill, order_update, balance.
Order basics
- price is in the order’s own side: NO at 30¢ is the same book level as YES at 70¢.
- limit orders rest until filled or canceled. market orders fill immediately and cancel the rest;
priceis their worst acceptable price. - Buys reserve price × count cents; sells reserve the contracts. Holding YES and NO in one market nets to 100 cents ($1) per pair. All balances are USD cents.
- Errors look like
{"error":{"code","message"}}. Order placement is rate limited per key.