OREStats

OREStats API v1

Paid endpoints under /api/v1/*. All require Authorization: Bearer ore_…. Subscribe at /pricing.

Subscribing via API

  1. POST /api/v1/subscribe with { ownerPubkey } — server returns a unique nonce + ORE amount.
  2. Send the priceOre amount of ORE from step 1 to the treasury address (returned in the same response), attaching the nonce as an SPL Memo instruction.
  3. PUT /api/v1/subscribe with { nonce, txSig, ownerPubkey } — server verifies on-chain, activates subscription, returns your API key.
  4. Use Authorization: Bearer ore_… header on all /api/v1/* calls.

Payment details

Treasury wallet: A9HLwE6wCm7Hedo7771nwsX8TyArv7rgdVQMo9dgDGZF
ORE mint: oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhwyK9jSybcp
Network: Solana mainnet-beta
GET/api/v1/pricingpublic

purpose: Current price (in ORE) for one month of access. Price ladders up as more subs join — the response also tells you the next threshold and the price beyond it.

response:
{
  "activeSubs": 17,
  "oreNow": 0.1,
  "nextThreshold": 100,
  "oreAtNextThreshold": 0.2,
  "treasury": "...",
  "oreMint": "..."
}
POST/api/v1/subscribepublic

purpose: Step 1 of subscribing. Returns a one-shot SPL transfer instruction (memo + amount) you must sign with the owner wallet and broadcast on Solana.

parameters:
  • ownerPubkeybase58 Solana pubkey that will own the API key
request body:
{ "ownerPubkey": "..." }
response:
{
  "nonce": "ore-pay-...",
  "priceOre": 0.1,
  "instructions": { "to": "...", "memo": "ore-pay-...", "amountBaseUnits": "10000000000", "mint": "..." },
  "expiresAt": "..."
}
PUT/api/v1/subscribepublic

purpose: Step 2 of subscribing. After the SPL transfer confirms, submit the tx signature to mint your API key. The plaintext key is shown ONCE.

parameters:
  • noncevalue returned from POST /subscribe
  • txSigconfirmed SPL transfer signature carrying the memo from step 1
  • ownerPubkeymust match the wallet that paid (and was passed to POST)
request body:
{ "nonce": "...", "txSig": "...", "ownerPubkey": "..." }
response:
{
  "apiKey": "ore_xxx (shown ONCE)",
  "subscriberId": "sub_...",
  "paidUntil": "..."
}
GET/api/v1/livepaid (Bearer)

purpose: Current round snapshot — what every square holds right now, seconds remaining, and last round's result. Cheap; safe to poll every 1-2 s.

response:
current round snapshot (deployed, count, secondsLeft, prevRound)
GET/api/v1/streampaid (Bearer)

purpose: SSE feed of /live. Pushes a fresh snapshot whenever the on-chain board or round account changes. Reconnect any time — the next event is always the latest state.

response:
server-sent events; pushes a snapshot on every on-chain board / round account change
GET/api/v1/statspaid (Bearer)

purpose: Aggregated grid statistics: chi-squared on cumulative hits, per-square hit count & deployed SOL, total SOL ever deployed, effective house edge.

response:
aggregate (chi-squared, perGrid, totalDeployedSol, effectiveHouseEdge)
GET/api/v1/rounds?limit=100paid (Bearer)

purpose: Last N indexed rounds, newest first. Use this for batch ingest; for low-latency new-round alerts use /events/stream.

parameters:
  • limitnumber of rounds to return; default 100, max 10000
response:
last N indexed rounds (id, deployed[25], count[25], winningSquare, totalDeployed, totalWinnings)
GET/api/v1/rounds/{id}paid (Bearer)

purpose: Single round detail with prev/next ids for cursor traversal of history.

parameters:
  • idround id (path segment)
response:
single round + prev/next ids
GET/api/v1/grid/{n}?limit=200paid (Bearer)

purpose: Per-square stats plus the recent hit/miss series (1 = hit, 0 = miss) for chart rendering.

parameters:
  • nsquare index 0..24 (path segment)
  • limitseries length; default 200
response:
per-grid stat + recent hit/miss series (1 ≤ n ≤ 25)
GET/api/v1/events?since=N&limit=M&kind=Xpaid (Bearer)

purpose: Polled event log. Includes drought-broken, big-round, tier-crossing, milestones, subscription changes. Pull events newer than the `since` cursor.

parameters:
  • sinceid cursor; only events with id > since are returned
  • limitmax events per call; default 100
  • kindoptional filter: drought_broken | big_round | tier | milestone | subscription
response:
{
  "count": 12,
  "lastId": 47,
  "events": [
    { "id": 47, "ts": "...", "kind": "drought_broken", "grid": 8, "drought": 91, "roundId": 247101 },
    { "id": 48, "ts": "...", "kind": "big_round", "roundId": 247155, "deployedSol": 8.94, "thresholdSol": 8.15, "multiplier": 1.10, "winningSquare": 12, "totalMiners": 209 },
    ...
  ]
}
GET/api/v1/events/stream?since=N&kind=Xpaid (Bearer)

purpose: SSE feed of the same event log as /events. Replays last 50 events (or events since cursor) on connect, then pushes each new event live.

parameters:
  • sinceoptional replay cursor; if omitted, replays last 50
  • kindoptional filter (same set as /events)
response:
server-sent events; replays last 50 (or events since cursor) on connect, then pushes each new event as it fires (drought / streak / big round / tier / milestone / subscription).
GET/api/v1/dump?from=X&to=Y&limit=10000paid (Bearer)

purpose: Bulk historical export — page through all indexed rounds via `from` / `nextFrom` cursors. Use this to bootstrap your own database, then switch to /events/stream for incremental updates.

parameters:
  • fromstarting round id (inclusive)
  • tooptional ending round id (inclusive)
  • limitpage size; default 5000, max 10000
response:
{
  "count": 5000,
  "from": 228237,
  "to": 233236,
  "hasMore": true,
  "nextFrom": 233237,
  "rounds": [ { id, deployed[25], count[25], winningSquare, totalDeployed, totalWinnings }, ... ]
}
POST/api/v1/reissuepublic

purpose: Step 1 of rotating an API key. Returns a message you must sign with the wallet that owns the active subscription.

parameters:
  • ownerPubkeywallet that originally subscribed
request body:
{ "ownerPubkey": "..." }
response:
{ "nonce": "ore-reissue-...", "message": "OREStats reissue ... @ ...", "expiresAt": "..." }
PUT/api/v1/reissuepublic

purpose: Step 2 of rotation. Submit the wallet signature; old key is revoked immediately and a new key is returned (also shown ONCE).

parameters:
  • noncevalue returned from POST /reissue
  • ownerPubkeysame wallet as POST
  • signatureBase64base64-encoded ed25519 signature of the message string
request body:
{ "nonce": "...", "ownerPubkey": "...", "signatureBase64": "..." }
response:
{ "apiKey": "ore_xxx (NEW, old key revoked)", "subscriberId": "sub_...", "paidUntil": "..." }

Strategy Lab

Build, backtest, and forward-test parameterized strategies. The create / backtest / analytics endpoints share one DSL shape — see the values reference at the bottom of this section.

POST/api/v1/lab/strategiespaid (Bearer)

purpose: Create a strategy. Once active, OREStats automatically records a paper-trading prediction for every new round and surfaces forward-test stats.

parameters:
  • namedisplay label, non-empty string
  • dslfull Strategy DSL — base_strategy, params, optional filters[]. See values reference below.
request body:
{
  "name": "my cold-5",
  "dsl": {
    "base_strategy": "cold",
    "params": {
      "bet_size_lamports": 200000,
      "num_squares": 5,
      "sizing_mode": "flat",
      "max_bet_per_square_lamports": 5000000,
      "tx_fee_lamports": 10000
    },
    "filters": [
      { "metric": "current_drought_min", "op": ">=", "value": 30 }
    ]
  }
}
response:
{
  "strategy": {
    "id": "...", "owner": "...", "name": "...",
    "dsl": { "base_strategy": "...", "params": { ... }, "filters": [ ... ] },
    "createdAt": "...", "updatedAt": "...", "active": true
  }
}
GET/api/v1/lab/strategiespaid (Bearer)

purpose: List your owned strategies with live forward-test stats (rounds settled, win count, ROI on real round outcomes).

response:
{
  "count": 3,
  "strategies": [
    {
      "id": "...", "name": "...", "dsl": { ... }, "active": true,
      "stats": { "roundsSettled": 412, "roundsWon": 88, "netProfitSol": 0.123, "roiPercent": 4.7 }
    },
    ...
  ]
}
GET/api/v1/lab/strategies/{id}paid (Bearer)

purpose: Fetch a single strategy you own, with its prediction count.

parameters:
  • idstrategy id (path segment)
response:
{ "strategy": { ... }, "predictionCount": 412 }
PATCH/api/v1/lab/strategies/{id}paid (Bearer)

purpose: Rename a strategy or toggle its active flag. Inactive strategies stop being predicted on new rounds but their history is preserved.

parameters:
  • namenew display name (optional)
  • activetrue to resume predictions, false to pause (optional)
request body:
{ "name": "renamed", "active": false }
response:
{ "strategy": { ... } }
DELETE/api/v1/lab/strategies/{id}paid (Bearer)

purpose: Hard delete a strategy you own. All linked predictions are removed; the leaderboard entry (if any) disappears.

parameters:
  • idstrategy id (path segment)
response:
{ "ok": true }
GET/api/v1/lab/strategies/{id}/forwardpaid (Bearer)

purpose: Forward-test stats for one strategy: net SOL, ROI, win rate, equity curve, max drawdown, max losing streak, pending unsettled rounds.

parameters:
  • idstrategy id (path segment)
response:
{
  "strategyId": "...",
  "roundsObserved": 432,
  "roundsBet": 412, "roundsWon": 88,
  "squaresBet": 2060, "squaresWon": 92,
  "netProfitSol": 0.12, "totalStakeSol": 2.6,
  "roiPercent": 4.7, "winRate": 0.21, "perSquareWinRate": 0.045,
  "maxDrawdownSol": 0.08, "maxStreak": 12,
  "equityCurve": [{ "round": 247001, "balanceLamports": 0 }, ...],
  "pendingCount": 1
}
POST/api/v1/lab/backtestpaid (Bearer)

purpose: Replay a DSL against the indexed historical rounds. Returns full BacktestResult including per-round PnL, per-square contribution, equity curve, and early-exit reason.

parameters:
  • dslStrategy DSL (same shape as create)
  • fromRoundIdoptional inclusive lower bound of replay window
  • toRoundIdoptional inclusive upper bound
request body:
{
  "dsl": { "base_strategy": "...", "params": { ... }, "filters": [ ... ] },
  "fromRoundId": 200000,
  "toRoundId": 247000
}
response:
{
  "result": {
    "totalRounds": 47000, "roundsBet": 9200, "roundsWon": 1800,
    "squaresBet": 46000, "squaresWonOn": 1900,
    "netProfitLamports": ..., "netProfitSol": ...,
    "totalStakeLamports": ..., "totalStakeSol": ...,
    "totalRecoveryLamports": ..., "totalRecoverySol": ...,
    "roiPercent": ..., "winRate": ..., "perSquareWinRate": ...,
    "maxStreak": ..., "capHits": ..., "totalCapLossSol": ...,
    "minWalletSol": ..., "maxDrawdownSol": ...,
    "rangeMin": 200000, "rangeMax": 247000,
    "exitedEarly": null,
    "exitRoundId": 0,
    "equityCurve":   [{ "round": ..., "balanceLamports": ... }, ...],
    "perSquare":     [{ "square": 0, "betCount": ..., "winCount": ..., "netLamports": ... }, ...],
    "perRoundPnlLamports": [...],
    "streakRunLengths":    [...]
  }
}
POST/api/v1/lab/analyticspaid (Bearer)

purpose: Heavy analytics bundle — Monte-Carlo confidence intervals plus four nested backtests across parameter sweeps. Expect 3-6 s on first call, sub-second on warm cache. Cache key is the DSL.

parameters:
  • dslStrategy DSL (same shape as backtest)
request body:
{ "dsl": { ... } }
response:
{ "analytics": { ... } }
GET/api/v1/lab/leaderboardpublic

purpose: Public top-strategies list. Only ROI / sample size is exposed; the DSL is hidden until a subscriber views the detail endpoint.

response:
{
  "generatedAt": "...",
  "minRoundsToQualify": 1000,
  "count": 14,
  "entries": [
    { "id": "...", "name": "...", "ownerShort": "abcd...wxyz", "roiPercent": ..., "roundsSettled": ... },
    ...
  ]
}
GET/api/v1/lab/leaderboard/{id}paid (Bearer)

purpose: Full DSL of a single leaderboard entry, plus its forward-test summary and equity curve. Gated to subscribers — public users only see the top-line ROI.

parameters:
  • idstrategy id (path segment)
response:
{
  "strategy": {
    "id": "...", "name": "...", "ownerShort": "abcd...wxyz",
    "dsl": { ... },
    "createdAt": "..."
  },
  "forwardTest": {
    "roundsSettled": ...,
    "netProfitSol": ...,
    "equityCurve": [{ "round": ..., "balanceLamports": ... }, ...]
  }
}

Strategy DSL — accepted values

base_strategy cold, spread, drought, custom_squares, hot, top_hit_rate, bottom_hit_rate, recent_winners, anti_spread, min_miners, corners, edges, center_block, diagonal_main, diagonal_anti, row, column, checkerboard, all_25

params.sizing_mode flat, martingale, reverse_martingale, fibonacci, dalembert, kelly

filters[].metric rounds_since_last_big, consecutive_losses, current_drought_min, current_drought_max, total_deployed_pctile, total_miners, rounds_since_big_round, chi_square_p_recent

filters[].op < , <= , > , >= , ==

params.* numeric ranges (server clamps out-of-range values):
  bet_size_lamports             required, (0, 1e8]
  num_squares                   1..25
  drought_threshold             1..1000
  custom_squares                int[] in 0..24
  hit_rate_lookback             50..20000
  row_index, column_index       0..4
  martingale_multiplier         1..10
  loss_streak_threshold         1..100
  dalembert_step_lamports       1..1e6
  kelly_fraction                0.0001..1
  kelly_bankroll_lamports       >= 1
  max_bet_per_square_lamports   1..1e8
  tx_fee_lamports               0..1e7
  stop_loss_streak              1..1000
  cooldown_after_loss_rounds    0..500
  take_profit_lamports          >= 0
  session_stop_loss_lamports    >= 0

quotas:
  max 100 strategies per account

Limits & fair use

  • Per API key: 5 req/sec (burst 60). 429 with Retry-After on overflow.
  • API key in header is single-use plaintext: store it — only the hash is kept.
  • Sharing keys is detectable (concurrent IPs) and may trigger revocation.
  • Dashboard endpoints (/api/live*) require browser session + Origin match — they are not for programmatic use.