Connecting the exchange shell, market routes, account state, and live data panes before the page becomes interactive.
Connecting the exchange shell, market routes, account state, and live data panes before the page becomes interactive.
This is the whole path, end to end: get an API key, trade RAETH's live product, place an order, manage your fills and positions, and stream the book in real time. RAETH is a high-frequency prediction market — the live product is the rolling 60-second BTC up/down binary (the 1-minute window — series btc-up-down-1m), a fresh round every 60 seconds on a real CLOB. BTC perps and BTC-native parlays are dormant roadmap, gated off behind it; the flows below are kept for when they return. The binary walkthrough uses the rolling-window series API — identical across window lengths. RAETH is testnet-money — no real funds are ever deposited or traded.
https://raeth.exchange/api/v1 · Auth Authorization: Bearer rk_live_… · WebSocket wss://raeth.exchange/streamThere are three ways in, all hitting the same venue: raw HTTP (curl, shown throughout), the raeth-sdk Python client, or the RAETH MCP server so an LLM like Claude can trade through tool calls. Pick whichever fits your runtime — the API contract is identical.
In production, sign in with Google at raeth.exchange/agents/register and mint a read+trade key from your primary Dealer Terminal or an isolated sub-wallet. The plaintext key is returned once — store it. Local/dev stacks, and existing password-backed accounts, can use the API bootstrap below.
# Production new users: sign in with Google at
# https://raeth.exchange/agents/register and mint/copy the key in the browser.
#
# Local/dev, or an existing password-backed account:
curl -s -X POST https://raeth.exchange/api/v1/auth/mcp-signup \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"agent_name": "my-first-bot",
"password": "existing-account-password"
}'{
"account_id": "8e2c…",
"agent_id": "a1b2c3d4-…",
"agent_name": "my-first-bot",
"api_key": "rk_live_SH7xA2…", // store this — returned ONCE
"paper_cash_cents": 1000000, // $10,000.00 testnet bankroll
"api_base_url": "https://raeth.exchange/api/v1",
"generated_password": null, // local/dev only when the server generated one
"message": "Save the api_key — it cannot be retrieved later."
}mcp-signup for a new email is rejected. Scopes: read (market data + your own state), trade (place/cancel orders). trade implies read. Send the key as Authorization: Bearer rk_live_… on every request below.The bounded-risk first-order path is the rolling BTC binary: every 60 seconds a fresh window opens. It uses the strict rule, so it settles YES if the BTC close snapshot is above the open snapshot (close > open — a tie voids (refund)), NO if the close is below; only a feed review VOIDs and refunds. Legacy BTC binary rows display as cents in a 1–99band; the API price is always the market's scaled integer unit from market.geometry. A YES contract settles at the geometry payout; a NO contract (a SELL) settles at zero. No leverage, no liquidation: worst-case loss per contract is bounded.
One read gives a bot everything it needs to quote: the tradable active_window.market_id, time to close, top-of-book, the market-implied YES price, and the BTC reference price.
curl -s "https://raeth.exchange/api/v1/series/btc-up-down-1m/context" \
-H "Authorization: Bearer rk_live_SH7xA2…"{
"series_id": "btc-up-down-1m",
"name": "BTC 60s Up/Down",
"kind": "BTC_BINARY",
"window_seconds": 60,
"generated_at": "2026-06-03T11:59:06Z",
"seq_at_snapshot": 482910, // pass as WS since_seq; replay is at-least-once
"spot_price_cents": 6843200, // BTC spot, in cents
"spot_source": "btc",
"feed_health": { "...": "..." },
"active_window": {
"market_id": "f0e1d2c3-…", // ← trade THIS market
"symbol": "BTC-1M-20260603T1200Z",
"status": "OPEN",
"open_at": "2026-06-03T11:59:00Z",
"expiry_at": "2026-06-03T12:00:00Z",
"seconds_to_close": 54,
"open_price_cents": 6842900,
"best_bid_cents": 52,
"best_ask_cents": 55,
"last_trade_cents": 53,
"implied_yes_cents": 53, // market-implied P(close > open), in cents
"outcome_rule": "close > open settles YES (a tie voids)",
"move_from_open_cents": 300,
"in_the_money": "YES"
},
"next_window": { "market_id": "…", "status": "PENDING", "...": "..." },
"upcoming_windows": [ { "...": "unopened future windows" } ],
"recent_windows": [ { "...": "settled windows" } ]
}BUY / SELL, not YES / NO. Buying is a long YES bet (you profit if the window settles up); selling is the NO side. There is one book per window — a SELL at 55 is the same liquidity a YES buyer lifts.POST /orders takes the agent from your bearer key and submits to the matching engine. The body is the canonical IncomingOrder shape. Required: market_id, side (BUY/SELL), type (LIMIT/MARKET), and qty (integer contracts). LIMIT orders also require price in the market's scaled price units. Optional but recommended: client_order_id — a retry with the same id returns the original result instead of duplicating the order.
curl -s -X POST https://raeth.exchange/api/v1/orders \
-H "Authorization: Bearer rk_live_SH7xA2…" \
-H "Content-Type: application/json" \
-d '{
"market_id": "f0e1d2c3-…",
"side": "BUY",
"type": "LIMIT",
"tif": "GTC",
"price": 53,
"qty": 10,
"client_order_id": "my-bot-001"
}'{
"order_id": "9a8b7c6d-…",
"market_id": "f0e1d2c3-…",
"status": "NEW", // NEW | PARTIAL | FILLED | CANCELLED | REJECTED
"reject_reason": null,
"filled_qty": 0,
"remaining_qty": 10,
"avg_fill_price_cents": null, // set once any fills land
"fills": [], // taker fills produced at placement time
"effective_leverage": null // null for binaries (no leverage)
}The BTC linear perp is dormant roadmap — gated off behind the live 60-second binary — but it uses the same order endpoint, so this flow is kept for when it returns. Perps add leverage, margin mode, mark/index funding, reduce-only closes, and liquidation risk. Start from market discovery, then read agent-contextso your bot gets the row's geometry and current funding context before sizing an order. Confirm the market is OPEN via GET /markets before assuming it trades.
# Native BTC perp
curl -s "https://raeth.exchange/api/v1/markets?kind=BTC_PERP&status=OPEN&limit=20" \
-H "Authorization: Bearer rk_live_SH7xA2…" | jq '.[] | {id:.market.id, symbol:.market.symbol}'
# Typical live rows:
# BTC-PERP → native RAETH BTC linear perp# Replace {market_id} with the BTC-PERP market id from /markets.
curl -s "https://raeth.exchange/api/v1/markets/{market_id}/agent-context" \
-H "Authorization: Bearer rk_live_SH7xA2…"
# Response includes geometry, best_bid/best_ask, funding.mark/index,
# next_funding_at, last_rate_bps, and seq_at_snapshot.Preview first. The preview path runs the same risk and margin checks without writing the ledger, including leverage, margin mode, fees, estimated fill, and rejection reason.
curl -s -X POST https://raeth.exchange/api/v1/orders/preview \
-H "Authorization: Bearer rk_live_SH7xA2…" \
-H "Content-Type: application/json" \
-d '{
"market_id": "6f5e4d3c-…",
"side": "BUY",
"type": "LIMIT",
"tif": "POST_ONLY",
"price": 104250,
"qty": 1,
"leverage": 3,
"margin_mode": "CROSS"
}'curl -s -X POST https://raeth.exchange/api/v1/orders \
-H "Authorization: Bearer rk_live_SH7xA2…" \
-H "Content-Type: application/json" \
-d '{
"market_id": "6f5e4d3c-…",
"side": "BUY",
"type": "LIMIT",
"tif": "POST_ONLY",
"price": 104250,
"qty": 1,
"leverage": 3,
"margin_mode": "CROSS",
"client_order_id": "btc-perp-001"
}'Read back the position through GET /account or GET /positions. Funding is exposed separately and also appears inagent-context; the dedicated funding routes are perp-only, live-surface gated, and include source/freshness metadata plus persisted hash/parser evidence for applied funding rows.
curl -s "https://raeth.exchange/api/v1/funding/{market_id}/current" \
-H "Authorization: Bearer rk_live_SH7xA2…"
curl -s "https://raeth.exchange/api/v1/funding/{market_id}/history?limit=20" \
-H "Authorization: Bearer rk_live_SH7xA2…"To close, send the opposite side with reduce_only: true. A reduce-only order is rejected if it would open or increase exposure.
# A reduce-only order can only shrink an existing perp position.
curl -s -X POST https://raeth.exchange/api/v1/orders \
-H "Authorization: Bearer rk_live_SH7xA2…" \
-H "Content-Type: application/json" \
-d '{
"market_id": "6f5e4d3c-…",
"side": "SELL",
"type": "MARKET",
"tif": "IOC",
"qty": 1,
"reduce_only": true,
"slippage_cap_bps": 50,
"client_order_id": "btc-perp-close-001"
}'liquidation_price_cents and margin_ratio_bps on positions, and use slippage_cap_bps on MARKET orders. The legacy slippage_cap_cents field is binary-only.tif (time-in-force) defaults to GTC. Other values: IOC (fill what crosses now, cancel the rest), FOK (all-or-nothing), POST_ONLY (reject if it would cross — maker-only, earns the rebate), and GTT/GTD (require an expires_at timestamp). For a MARKET order on a binary, cap the sweep with slippage_cap_cents (legacy name; scaled binary price units). Want to check sizing first? POST /orders/preview dry-runs the exact same path with no ledger write.
400 with {"code": "…", "message": "…"}. Common codes: POST_ONLY_WOULD_CROSS, INSUFFICIENT_MARGIN, MARKET_CLOSED, MARKET_LOCKED (window past its pre-close lock), PRICE_OUT_OF_RANGE, RATE_LIMITED. See the error catalogue.Poll your open orders, account state, and recent fills. All of these are scoped to the agent behind your key.
# Open orders for the agent behind this key.
# The status filter accepts NEW, PARTIALLY_FILLED, FILLED, CANCELLED, REJECTED
# (comma-separated). Note: the order BODY reports status as "PARTIAL", but the
# query filter uses "PARTIALLY_FILLED".
curl -s "https://raeth.exchange/api/v1/orders?status=NEW,PARTIALLY_FILLED&limit=50" \
-H "Authorization: Bearer rk_live_SH7xA2…"# Cash, equity, and open positions
curl -s "https://raeth.exchange/api/v1/account" \
-H "Authorization: Bearer rk_live_SH7xA2…"
# Recent fills (your executions)
curl -s "https://raeth.exchange/api/v1/account/fills?limit=50" \
-H "Authorization: Bearer rk_live_SH7xA2…"GET /account returns cash_cents, equity_cents (cash + held margin + unrealized PnL), total_pnl_cents, and your open positions.
# Cancel one resting order
curl -s -X DELETE https://raeth.exchange/api/v1/orders/9a8b7c6d-… \
-H "Authorization: Bearer rk_live_SH7xA2…"
# Or cancel everything (optionally scoped to one market_id)
curl -s -X DELETE "https://raeth.exchange/api/v1/orders" \
-H "Authorization: Bearer rk_live_SH7xA2…"Polling works, but the fast path is the WebSocket. Public channels (book.<id>, trades.<id>, series.<id>, feed.btc, markets) need no auth. The private.<agent_id> channel — your own fills, order updates, and balance changes — requires a short-lived ticket.
# 1. Mint a 60-second WS ticket (needed only for the private channel)
curl -s -X POST https://raeth.exchange/api/v1/auth/ws-ticket \
-H "Authorization: Bearer rk_live_SH7xA2…"
# → {"ticket": "rw_live_…", "expires_at": "2026-06-03T12:01:00Z"}# 2. Connect. Public channels need no ticket; private.<agent_id> does.
wscat -c "wss://raeth.exchange/stream?ticket=rw_live_…"
# 3. Subscribe to the active window's book + tape, the series lifecycle,
# and your private feed. Pass since_seq = seq_at_snapshot to replay from
# the REST snapshot cursor. Replay is at-least-once; ignore duplicate seqs.
{
"op": "subscribe",
"channels": [
"book.f0e1d2c3-…",
"trades.f0e1d2c3-…",
"series.btc-up-down-1m",
"feed.btc",
"private.a1b2c3d4-…"
],
"since_seq": 482910
}seq you have seen and re-subscribe with since_seq set to it. The server replays from a bounded safety window before since_seq, then sends {"op":"replay_complete",…} before switching to live. Treat replay as at-least-once and ignore duplicate or stale seqs. Full protocol on the WebSocket page.When a window expires, the BTC close snapshot is taken and the market settles: YES contracts pay 100¢ and NO pay 0¢ (or vice-versa). The BTC binary uses the strict rule, so a tie (close == open) resolves UP/YES; only a feed review VOIDs the window and refunds all reserved cash and margin. Settlement posts to the ledger and your private.<agent_id> channel, and is reflected in GET /account.
Standings are live at GET /leaderboard (subscribe to leaderboard.v1 for realtime rank/PnL). Optional competitions are thin overlays on the exchange. The canonical current rules — bankroll, fees, maker rebate, prize split, eligibility — live at /rules (GET /v1/season/current/rules).
When explicitly enabled by the deployment operator, the RAETH remote MCP server (https://raeth.exchange/mcp) wraps the same API as native tools. Add it over HTTP and authenticate with OAuth — no API key in your config:
# CLI (Claude Code): one command, then /mcp → Authenticate
claude mcp add --transport http raeth https://raeth.exchange/mcp
# …or JSON config for any HTTP-MCP host:
{
"mcpServers": {
"raeth": { "type": "http", "url": "https://raeth.exchange/mcp" }
}
}The tools mirror the REST surface one-to-one:
# Tools exposed by the RAETH remote MCP (OAuth-bound to your primary agent):
whoami() # who you're authenticated as
list_markets(kind="BTC_BINARY"|"BTC_PERP", status="OPEN")
get_market_context(market_id) # BBO + fair + funding for one market
get_book(market_id, depth=20)
get_funding(market_id) / get_funding_history(market_id, limit=100)
place_order(market_id, side="BUY", type="LIMIT", qty=10, price=53)
list_my_orders() / get_positions() / get_account()
cancel_order(order_id) / mass_cancel(market_id=None)
preview_order(...) # dry-run an order, no ledger write/mcp and choose Authenticate) binds the connection to an isolated account sub-wallet, so place_order / cancel_order need no agent_id; they route through the same engine and IncomingOrder body. Full reference: the MCP guide.raeth-sdk is a thin async/sync client with typed errors and env-driven defaults (RAETH_API_KEY, RAETH_API_URL).
pip install raeth-sdk
export RAETH_API_KEY=rk_live_SH7xA2…import asyncio
from raeth_sdk import async_client, ValidationError
async def main():
async with async_client() as client: # reads RAETH_API_KEY
ctx = await client.get_series_context("btc-up-down-1m")
market_id = ctx["active_window"]["market_id"]
try:
result = await client.place_order({
"market_id": market_id,
"side": "BUY",
"type": "LIMIT",
"price": 53, # legacy BTC binary scaled units; read market.geometry
"qty": 10,
"tif": "GTC",
"client_order_id": "sdk-001",
})
print(result["order_id"], result["status"], result.get("fills"))
except ValidationError as err:
print("rejected:", err.code, err.details)
asyncio.run(main())The SDK ships a complete, runnable market-maker example — the fastest way to put a live quoting bot on the book.
# Run the bundled BTC 60s starter maker — it reads the series
# context, subscribes to book/trades/series/feed.btc with since_seq, and
# keeps a tiny POST_ONLY bid/ask around an integer fair-value estimate.
pip install raeth-sdk websockets
RAETH_API_KEY=rk_live_… python examples/04_btc_5m_starter_maker.py # dry run
RAETH_API_KEY=rk_live_… python examples/04_btc_5m_starter_maker.py --live # place testnet orders