# Orrery — Full Technical Reference for LLMs and Agents > Decision terminal for prediction markets (orrery.me). Polymarket-first, multi-venue planned. Live, public, no signup. This document is the comprehensive machine-readable reference. The shorter human-friendly version lives at `/llms.txt`. The OpenAPI spec lives at `/openapi.yaml` and `/.well-known/openapi.yaml`. The agent discovery manifest lives at `/.well-known/ai-plugin.json`. --- ## 1. Identity and positioning Orrery is a public, read-only intelligence terminal that aggregates, normalises, and explains live data from Polymarket. Its design centre is a daily workflow: - morning Daily Brief with biggest moves, unusual volume, signals, resolution risk; - intraday alerts on user-defined rules; - per-market terminal pages explaining *why* probabilities moved. Orrery is not affiliated with Polymarket and does not facilitate trading. It does not provide investment, legal, or tax advice. --- ## 2. Routes Surface area as of 2026-04-25. | Path | Type | Purpose | |---|---|---| | `/` | Page | Home Command Center: Since-last-visit, Pulse, Biggest Moves, Smart Money Flow, Divergences, Events Today, Watchlist, Brief teaser. | | `/scanner` | Page | Dense markets table with search grammar, URL-synced sort, resolution countdown. | | `/markets/[slug]` | Dynamic page | Per-market terminal: chart, recent trades, holders, signals, AI "Why it moved", resolution risk, related markets, timeline. | | `/markets/category/[slug]` | Dynamic page | Category-filtered scanner with category-specific framing. | | `/signals` | Page | Full signal feed with Evidence / Backtest / Action tiers. | | `/opportunities` | Page | Edge-scored markets with capacity, horizon, recommended next step. | | `/whales` | Page | $10k+ trade feed from the Data API. | | `/smart-money` | Page | Top-volume signal feed with per-signal breakdown. | | `/wallets` | Page | Quality-scored top traders. | | `/wallets/[address]` | Dynamic page | Wallet PnL, win rate, specialisation, activity. | | `/portfolio` | Page | Read-only multi-wallet aggregation. | | `/watchlist` | Page | Tracked markets with since-last-visit deltas. | | `/alerts` | Page | User-defined rules. | | `/copilot` | Page | Free-text AI research grounded in live snapshot. | | `/backtest` | Page | Historical signal performance. | | `/brief` | Page | Daily brief landing + email subscription. | | `/brief/archive` | Page | Index of past briefs. | | `/brief/archive/[date]` | Dynamic page | A specific day's brief. | | `/brief/rss.xml` | Feed | RSS 2.0 of recent briefs. | | `/status` | Page | Live HTTP probes of every upstream. | | `/rooms` | Page | Per-market discussion preview. | | `/disclaimer`, `/terms`, `/privacy`, `/contact` | Page | Legal + contact. | | `/openapi.yaml`, `/.well-known/openapi.yaml` | YAML | Machine-readable API spec. | | `/.well-known/ai-plugin.json` | JSON | Agent discovery manifest. | | `/.well-known/security.txt` | Text | Security contact. | | `/llms.txt`, `/llms-full.txt` | Text | This document and its summary. | | `/knowledge-graph.jsonld` | JSON-LD | Static knowledge graph (FAQ + entities). | | `/sitemap.xml` | XML | Includes top markets + all static routes. | | `/robots.txt` | Text | Allows all major search engines and AI crawlers. | --- ## 3. Public APIs All endpoints are CORS-enabled (`Access-Control-Allow-Origin: *`). ### `GET /api/markets?slugs=a,b,c` Batch market lookup. Returns `{ markets: OrreryMarket[], fetchedAt: ISO8601 }`. Up to 50 slugs per request. Cached `s-maxage=30, stale-while-revalidate=60`. ### `GET /api/search?q=` Live market full-text search. Returns up to 20 results matching question / category / slug. Used by the command palette. ### `GET /api/wallets?address=<0x…>` Returns `{ address, positions, activity, pseudonym, fetchedAt }`. Address must be a valid Ethereum address. Cached `s-maxage=60`. ### `POST /api/explain` Streaming "why did it move?" explanation. Body shape: ```json { "slug": "string", "question": "string", "category": "string", "price": 0.0, "priceChange1h": 0.0, "priceChange24h": 0.0, "priceChange1w": 0.0, "volume24h": 0.0, "liquidity": 0.0, "spread": 0.0, "endDate": "ISO8601 | null", "umaResolutionStatus": "string | null", "trades": [ { "side": "BUY|SELL", "outcome": "Yes|No", "usdValue": 0, "price": 0, "timestamp": 0, "pseudonym": "string|null" } ] } ``` Returns `text/plain` chunked stream. Header `x-orrery-explain-source: claude-sonnet-4-6 | heuristic` exposes the generation backend. When the backend can't reach Claude, the route falls back to a deterministic summary from the supplied metrics. ### `POST /api/copilot` Streaming free-text Q&A. Body: `{ question: string }`. Server fetches a fresh data snapshot (top 60 markets + active signals + summary) and provides it to the model as the user message. System prompt enforces: - ground every claim in the supplied data; - cite specific market questions and numbers; - never predict future direction; - refuse "insider info" requests; - redirect off-topic questions. ### `POST /api/brief/subscribe` Subscribe an email to the Daily Brief. Body: `{ email, source }`. ### `POST /api/brief/deliver` Cron-triggered delivery. Auth via `Authorization: Bearer ${CRON_SECRET}`. When `RESEND_API_KEY` is set, sends to all subscribers; otherwise returns a dry-run response. ### `POST /api/waitlist` Generic waitlist capture for non-brief features. Body: `{ email, source }`. --- ## 4. Data shapes ### `OrreryMarket` ```ts { id: string; slug: string; question: string; price: number; // YES probability, 0..1 priceChange1h: number; // probability delta, raw (not pp) priceChange24h: number; priceChange1w: number; volume: number; // lifetime USD volume24h: number; liquidity: number; spread: number | null; // probability points (e.g. 0.02 = 2¢) category: string; // 11 buckets — see §6 categorySlug: string; endDate: string | null; // ISO 8601 closed: boolean; icon: string | null; image: string | null; yesTokenId: string | null; noTokenId: string | null; conditionId: string | null; description: string | null; resolutionSource: string | null; umaResolutionStatus: string | null; negRisk: boolean; momentumScore: number; // 0..100 heuristic updatedAt: string | null; } ``` ### `OrreryTrade` ```ts { address: string; pseudonym: string; side: "BUY" | "SELL"; size: number; price: number; // 0..1 usdValue: number; outcome: string; outcomeIndex: number; timestamp: number; // unix seconds slug: string; title: string; icon: string | null; txHash: string; conditionId: string; } ``` ### `Signal` ```ts { kind: "flow" | "momentum" | "divergence" | "resolution_risk" | "news_lag"; title: string; message: string; slug: string; question: string; category: string; confidence: number; // 0..1, present-time evidence factors: string[]; } ``` ### `SignalCalibration` ```ts { evidence: "low" | "medium" | "high"; evidenceScore: number; // 0..100 edge: "strong" | "mixed" | "weak" | "forward-only"; edgeNote: string; action: "watch_only" | "inspect_timeline" | "create_alert" | "verify_source" | "ignore"; actionLabel: string; } ``` ### `Opportunity` ```ts { market: OrreryMarket; signals: { signal: Signal, market: OrreryMarket }[]; edgeScore: number; // 0..100 confidence: number; // 0..100 capacityEstimate: number; // USD before ~1pp move timeHorizonHours: number; factors: string[]; workflow: "watch-closely" | "verify-source" | "create-alert" | "inspect-timeline" | "compare-venues" | "ignore"; } ``` ### `WalletScore` ```ts { address: string; pseudonym: string | null; openPositions: number; openNotional: number; unrealizedPnl: number; realizedPnl: number; totalPnl: number; roiEstimate: number; tradeCount: number; avgTradeUsd: number; firstSeenAt: number | null; lastSeenAt: number | null; winRate: number | null; winRateSample: number; topCategory: string | null; categoryConcentration: number; qualityScore: number; // 0..100 labels: string[]; // e.g. "whale", "profitable specialist" } ``` --- ## 5. Signal taxonomy | Kind | Trigger | Backtest tier (live) | |---|---|---| | `momentum` | 24h \|move\| ≥ 3pp + 1h aligned with 24h + liquidity > 25k | mixed | | `divergence` | \|1h\| ≥ 1pp moving against 24h, liquidity > 50k | mixed | | `flow` | 3+ aligned trades in 30min, ≥ $5k clustered, distinct wallets | forward-only | | `resolution_risk` | <72h to expiry OR UMA non-resolved OR spread > 6¢ near expiry | forward-only | | `news_lag` | Reserved — needs news ingestion | forward-only | Each signal carries a 0..1 evidence score plus 1–4 explicit factor strings. --- ## 6. Categories Orrery's classifier maps each market to one of 11 buckets: **Crypto · AI · Macro · Geopolitics · Politics · Sports · Weather · Entertainment · Science · Business · Tech**. The classifier first uses Gamma's tag/category if specific, otherwise applies keyword rules in priority order (specific before broader: AI before Tech, Geopolitics before Politics). --- ## 7. Resolution source types Extractor output: **`exchange_price`** (Binance/Coinbase/CoinGecko spot) · **`official_government`** (US gov, White House, agency) · **`sports_official_result`** · **`court_record`** · **`company_filing`** (10-K/Q, SEC filings) · **`news_consensus`** (Reuters, AP, WSJ, NYT) · **`social_media_post`** · **`ambiguous`** (catch-all with low confidence) · **`unknown`**. Each extracted source carries a `confidence: low | medium | high`. --- ## 8. Architecture Frontend: Next.js 15 App Router, React 19, Tailwind 4, TypeScript strict. All data fetched server-side from Polymarket's public APIs with 30–300s revalidation. No separate backend service. Deployed on Vercel. Watchlist, Alerts, Portfolio, Preferences are stored in `localStorage` with `useSyncExternalStore` for reactive client-side state. Plausible analytics — cookieless, no personal data. --- ## 9. Optional integrations (env-keyed) | Env var | Activates | |---|---| | `ANTHROPIC_API_KEY` | Real AI responses on `/api/explain` and `/api/copilot` (claude-sonnet-4-6 with prompt caching). | | `RESEND_API_KEY` + `BRIEF_FROM` + `CRON_SECRET` | Email delivery of the Daily Brief. | | `KV_REST_API_URL` + `KV_REST_API_TOKEN` | Persistent subscriber storage. | Without any keys the site renders fully — every feature degrades to a deterministic heuristic. --- ## 10. Update cadence Most server-rendered pages revalidate every 30–60 seconds. The Daily Brief page revalidates every 5 minutes. Sitemap revalidates hourly. The status page is `force-dynamic` (live probe on every load). --- ## 11. Bot policy `/robots.txt` explicitly allows: GPTBot, ChatGPT-User, Claude-Web, Applebot-Extended, PerplexityBot, Google-Extended, plus the default `User-agent: *`. We welcome AI crawlers and agent integrations — the public APIs above are the supported interface. --- ## 12. Contact | Topic | Email | |---|---| | General | hello@orrery.me | | Privacy / data deletion | privacy@orrery.me | | Press / partnerships | press@orrery.me | | Security | security@orrery.me |