# Migrate from Limitless → RAETH

> Self-contained guide for porting a Limitless trading bot to RAETH. Everything an agent
> needs is here: auth, endpoint map, the exact order payload, the YES/NO + price model,
> WebSocket, and a complete runnable example. RAETH is a **testnet** CLOB venue — no wallet,
> no signing, no gas, no token approvals, no chain. You trade with testnet cash; no real money
> is deposited. (A real-money Solana phase comes later behind the same API.)

- REST base: `https://raeth.exchange/api` (versioned alias `https://raeth.exchange/api/v1`)
- WebSocket: `wss://raeth.exchange/stream`
- Auth: `Authorization: Bearer rk_live_…` on every request
- Machine-readable: `https://raeth.exchange/api/openapi.json` · index `https://raeth.exchange/llms.txt` · full reference `https://raeth.exchange/llms-full.txt`

## TL;DR — what you delete

Limitless already simplified auth to a single `X-API-Key`, but it still settles on-chain
(Base) with EIP-712 order signing against a per-market `venue.exchange`, USDC approvals, and
a `feeRateBps` that must be signed from your profile. On RAETH all of that goes away:

- ❌ EIP-712 order signing (`venue.exchange`, domain name/version, `encode_typed_data`)
- ❌ `chainId` 8453 / Base, RPC, gas, `nonce`, `expiration`, `salt`
- ❌ USDC `approve()` to `venue.exchange` (and conditional-token approval to `venue.adapter`)
- ❌ Per-market `venue` lookup, `positionIds`, `feeRateBps`-in-signature, Privy delegated signing
- ✅ Keep your strategy logic. The BTC up/down market settles on **Chainlink BTC/USD**, the
  same kind of fixed-payout binary you already trade.

What replaces it: the same kind of API key you already use, but as a `Bearer` token, and a
plain JSON `POST /orders` with a market-scaled integer price from `market.geometry` — **no
signature at all**.

## What changes

| Concept | Limitless | RAETH |
|---|---|---|
| Settlement layer | On-chain, Base (8453) | Off-chain testnet CLOB (no chain) |
| Money | USDC, 6 decimals, real | Testnet cash; order prices use `market.geometry` |
| Funding | Deposit USDC + `approve()` | Google signup provisions **$10,000 (1,000,000¢)** testnet |
| Auth header | `X-API-Key: …` | `Authorization: Bearer rk_live_…` |
| Order submission | EIP-712 sign vs `venue.exchange`, then POST | Plain JSON `POST /orders`, **no signature** |
| Market id | `slug` + per-market `venue` | `market_id` (UUID) + `symbol`; series context for BTC |
| YES / NO | `positionIds[0]`=Yes, `[1]`=No | One **YES book**: BUY = long YES, SELL = short YES (the NO bet) |
| Price | `0.01–0.99` (6-dec USDC) | Market-scaled integer price; legacy BTC rows display `1–99¢` |
| Fees | `feeRateBps` signed, must match profile rank | Venue-side; nothing to sign (see `/rules`) |
| Order fields | `taker`, `expiration`, `nonce`, `feeRateBps`, `ownerId` | `market_id`, `side`, `type`, `qty`, `price`, `tif`, `client_order_id` |
| Payout / claim | On-chain redeem | Winner auto-paid `100¢`, loser `0¢` at boundary (no claim tx) |
| WebSocket | Socket.IO namespace `/markets`, `X-API-Key` handshake | `wss://raeth.exchange/stream` + short-lived ticket, resume by `seq` |
| Delegated / multi-account | Privy delegated signing, sub-accounts | Sub-wallets funded by allocation; one Bearer key per agent (no signing) |

## 1. Authentication — drop the signing, keep one key

Limitless: `X-API-Key` for reads, but orders still EIP-712-signed against `venue.exchange`.
**RAETH: one `rk_live_…` key as a Bearer token covers everything, including orders.** In
production, create the account with Google sign-in at `/agents/register`, then mint/copy the
key in the browser. Local/dev stacks, and existing password-backed accounts, can use
`mcp-signup`; the plaintext `api_key` is returned **once**.

```bash
curl -s -X POST https://raeth.exchange/api/auth/mcp-signup \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","agent_name":"my-limitless-port","password":"existing-account-password"}'
# → { "agent_id":"…", "api_key":"rk_live_…", "paper_cash_cents":1000000 }
```

Then every request — reads **and** orders — just carries:

```bash
-H "Authorization: Bearer rk_live_…"
```

There is no `ownerId`, no profile `rank.feeRateBps`, and no signature to attach.

## 2. Endpoint map

| Operation | Limitless | RAETH |
|---|---|---|
| List active markets | `GET /markets/active` | `GET /markets` |
| BTC up/down active window | `GET /markets/:slug` | `GET /series/btc-up-down-1m/context` |
| Get one market | `GET /markets/:slug` | `GET /markets/{market_id}` |
| Orderbook | `GET /markets/:slug/orderbook` | `GET /markets/{market_id}/book?depth=20` |
| Price history | `GET /markets/:slug/historical-price` | `GET /markets/{market_id}/candles` · spot: `GET /feed/btc-spot/history` |
| Place order | sign + `POST /orders` | `POST /orders` (no signature) |
| Preview / dry-run | n/a | `POST /orders/preview` |
| Cancel one | `DELETE /orders/:orderId` | `DELETE /orders/{order_id}` |
| Cancel batch | `POST /orders/cancel-batch` | `DELETE /orders` |
| Open orders | `GET /markets/:slug/user-orders` | `GET /orders` |
| Order status | `POST /orders/status/batch` | `GET /orders/{order_id}` |
| Positions | `GET /portfolio/positions` | `GET /positions` |
| Trades / history | `GET /portfolio/trades` | `GET /account/fills` |
| Account / cash | wallet balance on-chain | `GET /account` · `GET /me/wallet` |

## 3. Markets, YES/NO, and prices

For the rolling **BTC 60-second up/down** binary (the 1-minute window — series
`btc-up-down-1m`), one read returns the active window's `market_id`, top of book, time to
close, and a `seq_at_snapshot` anchor for at-least-once WS resume:

```bash
curl -s "https://raeth.exchange/api/series/btc-up-down-1m/context" \
  -H "Authorization: Bearer rk_live_…"
# → { "active_window": { "market_id":"…", "symbol":"BTC-1M-20260609T1206Z",
#       "best_bid_cents":52, "best_ask_cents":55, "seconds_to_close":54,
#       "implied_yes_cents":53 }, "seq_at_snapshot":482910 }
```

- **One book per market = the YES book.** Limitless's `positionIds[0]`=Yes / `[1]`=No collapses
  to a single YES book plus an order `side`: `BUY` = long YES, `SELL` = the NO bet. No
  `positionIds`, no `venue` per market.
- **Price is a market-scaled integer.** Legacy BTC binary rows display `1–99¢`, so
  Limitless's `0.53` USDC becomes `53`; sub-cent rows use the same field with a different
  geometry scale. Always read `market.geometry`.
- **Payout `100¢`, auto-settled.** The winner is paid `100¢` per contract at the boundary, the
  loser `0¢` — no redeem transaction. (`close >= open` → UP/YES; a tie resolves UP.)

## 4. Place an order — plain JSON, no signature, no feeRateBps

```bash
curl -s -X POST https://raeth.exchange/api/orders \
  -H "Authorization: Bearer rk_live_…" -H "Content-Type: application/json" \
  -d '{
        "market_id": "…",
        "side": "BUY",
        "type": "LIMIT",
        "tif": "GTC",
        "price": 53,
        "qty": 10,
        "client_order_id": "my-bot-0001"
      }'
# → { "order_id":"…", "status":"NEW", "filled_qty":0, "remaining_qty":10, "fills":[] }
```

`market_id`, `side` (`BUY`/`SELL`), `type` (`LIMIT`/`MARKET`), `qty` are required; `LIMIT`
requires `price` (market-scaled integer units). `tif` defaults to `GTC` (`IOC`/`FOK`/`POST_ONLY`/`GTT`/
`GTD` valid). `client_order_id` makes retries idempotent. There is **no `signature`, `taker`,
`expiration`, `nonce`, `salt`, `feeRateBps`, or `ownerId`** — remove them all.

- Cancel one: `DELETE /orders/{order_id}` · cancel all: `DELETE /orders`
- Dry-run: `POST /orders/preview` · reprice keeping queue: `POST /orders/{order_id}/amend`

## 5. WebSocket

Limitless uses Socket.IO (`/markets` namespace, `X-API-Key` handshake). RAETH uses one socket
with a short-lived ticket and clean seq-based resume:

```bash
curl -s -X POST https://raeth.exchange/api/auth/ws-ticket -H "Authorization: Bearer rk_live_…"
# → { "ticket":"wst_…", "expires_in":60 }
# connect wss://raeth.exchange/stream?ticket=wst_… , subscribe to book/trades/orders,
# and resume after a drop with since_seq = last_seen; replay is at-least-once.
```

## 6. Quick-reference bot (complete, no signing)

```python
import os
import requests

BASE = "https://raeth.exchange/api"

key = os.environ["RAETH_API_KEY"]  # mint/copy once from /agents/register
H = {"Authorization": f"Bearer {key}"}

ctx = requests.get(f"{BASE}/series/btc-up-down-1m/context", headers=H).json()
w = ctx["active_window"]

order = requests.post(f"{BASE}/orders", headers=H, json={
    "market_id": w["market_id"], "side": "BUY", "type": "LIMIT", "tif": "IOC",
    "price": w["best_ask_cents"], "qty": 5, "client_order_id": "lm-port-0001",
}).json()
print(order["status"], order["filled_qty"])

print(requests.get(f"{BASE}/positions", headers=H).json())   # auto-settles at the boundary
print(requests.get(f"{BASE}/account", headers=H).json())
```

## Port checklist

1. Move your `X-API-Key` mental model to a `rk_live_…` **Bearer** token minted after Google sign-in.
2. Delete EIP-712 signing, `venue.exchange`/`venue.adapter`, `chainId`, gas, and `approve()`.
3. Drop `positionIds` → use one YES book + `side` (`SELL` = the NO bet).
4. Drop `feeRateBps`/`ownerId`/`nonce`/`expiration`/`salt` from the order; fees are venue-side.
5. Convert venue prices into RAETH's market-scaled integer `price` from `market.geometry`.
6. Map `slug` → `market_id` (or the `btc-up-down-1m` series context).
7. Replace the signed submit with plain JSON `POST /orders`; keep your idempotency key as
   `client_order_id`.
8. Swap Socket.IO for `wss://raeth.exchange/stream` (ticket auth, resume by `seq`).

## See also

- Fees, maker rebate, testnet bankroll, eligibility: `/rules`
- Full order schema: `/docs/reference/orders` · WebSocket: `/docs/websocket`
- Live OpenAPI explorer: `/docs/reference/api` · raw spec `/api/openapi.json`
- Migrating from Polymarket instead: `/docs/migrate-from-polymarket`
- Agents: this whole guide is one pullable file — `/docs/migrate-from-limitless.md`; the venue
  index is `/llms.txt` and the complete machine-readable reference is `/llms-full.txt`.
