For developers

API & documentation

GuessWorks ships a public REST API for markets, signals, leaderboard, candles, and the trade tape. The full schema lives in the OpenAPI 3 spec; this page is the orientation.

Swagger UI

Interactive endpoint reference, served straight from the API.

OpenAPI 3 spec

Raw YAML. Drop into Postman, Bruno, or your generator of choice.

WebSocket feed

Live market + trade events at /ws (origin allow-listed).

API key program

Bearer keys lift the read limit from 20 r/s to 100 r/s.

Quick start

Every endpoint is reachable anonymously over HTTPS. No auth, no bearer header required for reads. The base URL is https://api.guessworks.app.

# Top-volume markets
curl https://api.guessworks.app/api/markets?column=latest&limit=10

# Per-market detail (with outcomes + bonding-curve state once matured)
curl https://api.guessworks.app/api/markets/<id>

# Sidebar signals
curl https://api.guessworks.app/api/signals?kind=trending&limit=8

# Global leaderboard, scoped to a calendar quarter
curl https://api.guessworks.app/api/leaderboard?season=current

# Aggregate platform stats (5s in-memory cache)
curl https://api.guessworks.app/api/stats

API key program

Anonymous read traffic is rate-limited to 20 r/s (burst 80) per IP. Holders of a public API key get their own bucket at 100 r/s (burst 400) — sized for legitimate ingest by integrators, dashboards, and chatbots.

Keys are issued by request. Send the bearer header on every read call you want to attribute:

curl -H "Authorization: Bearer gw_<prefix>_<secret>" \
  https://api.guessworks.app/api/markets?column=latest

Storage policy: only the SHA-256 of the key is persisted. A leaked DB cannot expose live keys. Plaintext is shown to the minter exactly once.

Examples

Same flow in three runtimes — fetch top markets, then connect to the WebSocket.

import requests, json, websocket
markets = requests.get(
    "https://api.guessworks.app/api/markets",
    params={"column": "latest", "limit": 10},
    headers={"Authorization": "Bearer gw_<prefix>_<secret>"},
).json()
print(markets[0]["question"])

ws = websocket.WebSocketApp(
    "wss://guessworks-api.fly.dev/ws",
    on_message=lambda _w, raw: print(json.loads(raw)["type"]),
)
ws.run_forever()

WebSocket feed

Connect to wss://guessworks-api.fly.dev/ws to receive live trade, market_update, and signals events. Origin must be allow-listed (set on the API as ALLOWED_ORIGINS); for local dev that includes http://localhost:3000.

{ "type": "trade",          "trade": { ... } }
{ "type": "market_update", "market": { ... } }
{ "type": "signals",       "kind": "trending", "rows": [ ... ] }

Posting a trade

Writes are signed-message gated. The user signs an EIP-191 (EVM) or ed25519 (Solana) message that references the wallet, market, outcome, side, amount, nonce, and a timestamp. The full envelope shape is in the OpenAPI spec — postMarketTrade. Server-side, the signature is verified after a cheap reject pass on timestamp window and message-content match, so malformed payloads fail fast.

Errors & rate limits

Errors are JSON: {"error": "<message>"}. Status codes follow REST conventions — 400 on validation, 401 on signature problems, 404 on missing resources, 409 on idempotency conflicts (replayed nonce), 429 on rate limit, 500 on internal failure. The 429 path adds a Retry-After: 5 header.

Need a key, hitting a wall, or want to embed a market card? Get in touch.