# API Route Inventory (for Kong / gateway fronting)

Auto-derived from `apps/web/src/app/api/**/route.ts` as of 2026-05-08. **544 route files** total (14 added 2026-04-26 for trade calendar + campaign watch; 1 added 2026-04-28 for `/api/cron/all-seeing-eye` in §4o-2; 7 added 2026-04-28 for imported datasets; 16 added 2026-05-07 for pattern scheduler; 3 added 2026-05-08 for economic calendar — see §4r-1). Next.js App Router flattens every `route.ts` into a URL path — this doc groups them by auth posture, rate-limit profile, and behavior quirks so a gateway config (Kong, Envoy, API Gateway, etc.) can lift directly from here.

**2026-05-08 update**: Pattern Hunter — Multi-market pattern scanning with timing analysis, warming detection, and quick alert setup. 5 new endpoints under `/patterns/hunter/*` (scan, history, quick-alert, export, stream). See `docs/58-pattern-hunter.md`. Economic Calendar — Unified economic calendar from Finnhub, FXStreet (OAuth2), and FRED. 3 new endpoints under `/economic-calendar/*` (events, releases) and `/admin/economic-calendar/sync`. Migration 191. See `docs/57-economic-calendar-integration.md`. **AI Stock Hunter** — Claude-powered stock research and recommendation system. Aggregates fundamentals (Finnhub), technicals, sentiment, patterns, then generates research-backed trade recommendations with thesis, risk assessment, price levels, and data citations. 7 endpoints under `/stock-hunter/*` + 5 admin endpoints under `/admin/stock-hunter/*`. Migrations 192 (core tables) + 193 (39 presets across 18 categories including pharma, biotech, medical devices, semiconductors, cybersecurity, clean energy, defense, fintech, etc.). Admin UI at `/admin/stock-hunter` for preset management.

**2026-05-07 update**: Pattern Scheduler — Complex pattern rules with AND/OR/NOT/THEN/XOR logic operators, timezone-aware time windows, multi-market scanning support, and visual drag-drop timeline (desktop-only). 16 new endpoints under `/patterns/scheduler/*`. Migration 188. See Pattern Scheduler section in §4o-2. **Candlestick Pattern Scanner** — 2 new endpoints under `/patterns/candle-scan/*` to scan symbols for 18 candlestick pattern types with backtest statistics.

**2026-05-05 update**: Derivatives support — perpetual swaps (Binance), exchange-traded futures (IBKR), short selling (all brokers). New body fields on paper/live run endpoints: `assetClass`, `leverage`, `brokerId`. Migration 143 (algorithm_runs/trades derivative columns) + Migration 144 (position_direction). See `docs/50-derivatives-and-shorts.md`.

**2026-04-28 update**: All-Seeing Eye list endpoints (insights / actions / black-swan) switched to **DB-first reads** with in-memory fallback so results survive Vercel serverless cold starts; orchestrator's `runCycle()` now persists actions + warnings to `omniscient.*` tables (insights persistence already existed). New Vercel Cron at `/api/cron/all-seeing-eye` runs the cycle every 15 minutes — see §4o-2. Per-user PANIC button (`POST /algorithms/panic` with `{all: true}`) now surfaced site-wide via the sidebar (typed-`yes` confirm + stopped-runs results modal) — see §4 algorithms row.

Patterns used throughout:
- `[param]` = dynamic path segment (Next.js syntax; Kong uses `:param`)
- **Auth**: `public` | `bearer` (JWT) | `bearer+active` (JWT + status=active) | `bearer+admin` (JWT + admin role) | `api-key` (X-API-Key header, `/api/public/v1/*` only) | `stripe-sig` (Stripe webhook signature)
- **Rate**: suggested rate-limit tier (low / mid / high / burst)
- **Notes**: SSE stream, webhook, long-running, etc.

All paths in the app are prefixed `/api/predict/v1/*` (private) or `/api/public/v1/*` (API-key) except `/api/health` (public liveness).

---

## 0. Complete Trading Workflow (End-to-End)

The platform provides a complete workflow from market identification to live trading or signal automation. The **All-Seeing Eye** orchestrates this entire pipeline, guiding users through each stage with AI-powered assistance.

### Workflow Stages

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           ALL-SEEING EYE ORCHESTRATION                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  Stage 1: MARKET IDENTIFICATION                                              │
│  ├── Market data aggregation (crypto, stocks, forex, derivatives)            │
│  ├── Sentiment analysis (7 social platforms)                                 │
│  ├── Prediction market signals (Polymarket, Kalshi, Metaculus, PredictIt)    │
│  └── Black Swan detection + anomaly alerts                                   │
│                                      ↓                                       │
│  Stage 2: OPPORTUNITY DISCOVERY                                              │
│  ├── AI-generated insights + probability forecasts                           │
│  ├── Convergence analysis (correlation matrix)                               │
│  ├── Human vs Bot divergence signals                                         │
│  └── Pattern matching against historical events                              │
│                                      ↓                                       │
│  Stage 3: ALGORITHM SELECTION/CREATION                                       │
│  ├── Strategy Templates (6 pre-built: Momentum, Mean Reversion, etc.)        │
│  ├── DSL Builder (40 primitives, natural language translation)               │
│  ├── AI Suggestions (LLM-powered optimization recommendations)               │
│  └── Import existing strategies                                              │
│                                      ↓                                       │
│  Stage 4: TESTING & VALIDATION                                               │
│  ├── Standard Backtest (historical performance, 12 metrics)                  │
│  ├── Walk-Forward Analysis (overfitting detection)                           │
│  ├── Monte Carlo Simulation (1000+ paths, VaR, CVaR, probability of ruin)    │
│  └── Risk Control Configuration (position limits, stop-loss, drawdown)       │
│                                      ↓                                       │
│  Stage 5: PAPER TRADING (Graduation Track)                                   │
│  ├── Live metrics tracking (equity curve, PnL, Sharpe)                       │
│  ├── Real-time alerts + breach notifications                                 │
│  ├── Performance requirements (30 days, 50 trades, Sharpe > 1.0)             │
│  └── Leaderboard participation (optional)                                    │
│                                      ↓                                       │
│  Stage 6: GO LIVE (Two Paths)                                                │
│  ├── Path A: BROKER INTEGRATION                                              │
│  │   ├── MFA-gated risk acknowledgment                                       │
│  │   ├── Paper-to-live graduation                                            │
│  │   └── Direct trade execution (Alpaca, IBKR, Binance)                      │
│  └── Path B: SIGNAL AUTOMATION                                               │
│      ├── Webhook triggers (custom endpoints)                                 │
│      ├── Slack/Discord/Teams notifications                                   │
│      ├── Email alerts with trade suggestions                                 │
│      └── API-key access for external platforms                               │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

### API Endpoints by Workflow Stage

| Stage | Key Endpoints | Purpose |
|-------|--------------|---------|
| **1. Market ID** | `GET /all-seeing-eye/data`, `GET /overlays/*`, `GET /derivatives/*` | Aggregate market data |
| **2. Opportunities** | `GET /all-seeing-eye/insights`, `GET /insights/human-automation/batch` | AI-generated opportunities |
| **3. Algorithms** | `GET /algorithms/templates`, `POST /algorithms/translate`, `POST /algorithms` | Create/select strategies |
| **4. Testing** | `POST /algorithms/:id/backtest`, `POST /algorithms/:id/walk-forward`, `POST /algorithms/:id/monte-carlo` | Validate performance |
| **5. Paper Trading** | `POST /algorithms/:id/runs`, `GET /algorithms/:id/live-metrics`, `GET /algorithms/:id/graduation` | Paper trade + track |
| **6a. Go Live** | `POST /algorithms/:id/graduation/acknowledge`, `PUT /algorithms/:id/graduation`, `PATCH /user/brokers/:id/mode` | Graduate to live |
| **6b. Signals** | `POST /user/webhooks`, `POST /triggers`, `POST /notifications/*` | External automation |

### All-Seeing Eye as Workflow Orchestrator

The All-Seeing Eye (`/api/predict/v1/all-seeing-eye/*`) serves as the central AI brain that:

1. **Monitors** all market data sources in real-time
2. **Generates** actionable insights with confidence scores
3. **Suggests** algorithms based on current market conditions
4. **Validates** strategy proposals through dual-layer analysis
5. **Alerts** on black swan events and anomalies
6. **Tracks** algorithm performance across paper/live modes

SSE endpoints stream real-time updates:
- `/api/predict/v1/sse/all-seeing-eye/stream` — insights, warnings, status
- `/api/predict/v1/sse/algorithms/:id/live` — live metrics for running algorithms

### Signal Automation (Non-Broker Path)

For users who want to receive trading signals without direct broker integration:

| Method | Path | Purpose |
|--------|------|---------|
| POST | `/user/webhooks` | Register webhook endpoints for trade signals |
| POST | `/triggers` | Create conditional triggers (price, indicator, event) |
| POST | `/triggers/:id/actions` | Attach actions (webhook, email, Slack, Discord, Teams) |
| GET | `/api/public/v1/signals` | API-key authenticated signal feed for external platforms |
| GET | `/api/public/v1/predictions` | Latest AI predictions for external consumption |

### Safety Guardrails Throughout

Every stage includes safety mechanisms:
- **Stage 3**: DSL whitelist (40 approved primitives only)
- **Stage 4**: Cross-validation prevents overfitting
- **Stage 5**: Risk controls (max position, daily loss, drawdown limits)
- **Stage 6**: MFA-gated live trading, platform kill switch, idempotency keys

---

## 1. Public (no auth)

| Method | Path | Auth | Rate | Notes |
|---|---|---|---|---|
| GET | `/api/health` | public | burst | DB / Redis / storage probe — gateway liveness check; keep response < 500 ms |
| POST | `/api/predict/v1/billing/webhooks/stripe` | `stripe-sig` | burst | Raw-body required; sig verified via `STRIPE_WEBHOOK_SECRET`. Events: `checkout.session.completed` (credit purchases + subscriptions), `customer.subscription.*`, `invoice.*`. Updated 2026-04-30 to handle credit purchases when License Server not configured. |
| POST | `/api/predict/v1/webhooks/license-server` | `hmac-sig` | burst | Raw-body required; HMAC-SHA256 sig verified via `LICENSE_SERVER_WEBHOOK_SECRET`. Events: credits.purchased, credits.refunded, credits.auto_refill.*, credits.balance_sync. Shipped 2026-04-30. |
| POST | `/api/predict/v1/billing/webhooks/license-server` | `hmac-sig` | burst | Subscription + license events from License Server: checkout.completed, subscription.*, license.*. Also routes credit events to the main handler. Shipped 2026-04-30. |

---

## 2. Auth flows (public → bearer mid-flow)

Kong should allow these without JWT checks and let the backend do its own rate-limit on failed attempts.

| Method | Path | Auth | Rate | Notes |
|---|---|---|---|---|
| POST | `/api/predict/v1/auth/login` | public | low | Returns `{user, token}` or `{challenge, session}` for MFA. Creates session record with device/IP/location. If at session limit (default 5), evicts oldest session. |
| POST | `/api/predict/v1/auth/register` | public | low | Self-service signup |
| POST | `/api/predict/v1/auth/verify-email` | public | low | 6-digit code, enumeration-safe |
| POST | `/api/predict/v1/auth/resend-verification` | public | low | 60s server-side cooldown, 429 with `Retry-After` |
| POST | `/api/predict/v1/auth/forgot-password` | public | low | Always 200 for well-formed requests |
| POST | `/api/predict/v1/auth/reset-password` | public | low | `{email, code, newPassword}` |
| POST | `/api/predict/v1/auth/mfa/challenge` | public+session | low | Session token from `/auth/login` response |
| POST | `/api/predict/v1/auth/refresh` | public+refresh-token | mid | Returns new access token |
| GET | `/api/predict/v1/auth/providers` | public | high | Lists active auth providers + config |
| POST | `/api/predict/v1/auth/logout` | bearer | mid | Revokes current session record + best-effort sign-out |
| GET | `/api/predict/v1/auth/me` | bearer | high | Current user + status + nextStep |

---

## 3. Onboarding (bearer, pending_* allowed)

| Method | Path | Auth | Rate | Notes |
|---|---|---|---|---|
| POST | `/api/predict/v1/auth/mfa/enroll/start` | bearer | low | Returns TOTP secret + otpauth URL |
| POST | `/api/predict/v1/auth/mfa/enroll/verify` | bearer | low | Advances `pending_mfa → pending_subscription` |
| POST | `/api/predict/v1/auth/mfa/disable` | bearer | low | Refused while `mfa_required=true` |
| GET | `/api/predict/v1/onboarding/status` | bearer | high | One-shot: plans + status + org context |
| POST | `/api/predict/v1/onboarding/checkout` | bearer | low | Stripe Checkout URL for per-user sub |
| GET | `/api/predict/v1/user/terms/status` | bearer | high | Checks if accepted version matches current |
| POST | `/api/predict/v1/user/terms/accept` | bearer | low | Writes acceptance + version |
| GET/POST | `/api/predict/v1/user/onboarding/status\|complete` | bearer | low | Legacy onboarding-tour signals |

---

## 4. User-scoped (bearer + active)

These need both a valid JWT and an `active` onboarding status. Apply `requireActiveUser` at the backend **and** a gateway-level JWT check as defense-in-depth.

### 4a. User preferences / settings
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET, PATCH | `/api/predict/v1/user/preferences` | mid | |
| GET, PUT | `/api/predict/v1/user/ai-settings` | mid | Organization BYOK + model preferences. See `docs/31-ai-llm-system.md` for full API key/metering documentation. |
| GET | `/api/predict/v1/user/ai-usage` | mid | AI usage stats (tokens, calls, cost by model/day). Query: `?days=30` (max 90). Admins/owners see full breakdown; members see aggregates. Shipped 2026-04-20. |
| GET, PUT | `/api/predict/v1/user/timezone` | mid | IANA zone validated against `pg_timezone_names` on write. Read by brief delivery dispatcher. Shipped 2026-04-19. |
| GET, PUT | `/api/predict/v1/user/slack-webhook` | low | User's Slack incoming-webhook URL for brief delivery (and future Slack-bound notifications). Slack-host URL validated on write. Shipped 2026-04-19. |
| DELETE | `/api/predict/v1/user/account` | **low** | Self-service account deletion. Requires password (local/agencio auth) + confirmation text "DELETE MY ACCOUNT". Handles Cognito deletion. Shipped 2026-04-20. |
| POST | `/api/predict/v1/user/avatar/presigned` | low | Get presigned URL for avatar upload. Body: `{contentType, fileSize}`. Returns `{uploadUrl, key}`. Max 2MB, JPG/PNG/GIF/WebP. Shipped 2026-04-20. |
| PUT | `/api/predict/v1/user/avatar` | low | Save avatar after upload. Body: `{key}`. Verifies file exists in storage. Returns `{avatarUrl, key}`. Shipped 2026-04-20. |
| DELETE | `/api/predict/v1/user/avatar` | low | Remove avatar from storage and database. Shipped 2026-04-20. |
| GET | `/api/predict/v1/user/sessions` | mid | List all active sessions for current user. Returns `{sessions, maxSessions, activeCount}`. Each session includes device info, IP, location, timestamps, `isCurrent` flag. Shipped 2026-05-04. |
| DELETE | `/api/predict/v1/user/sessions/[sessionId]` | low | Revoke a specific session. Cannot revoke current session (use logout). Returns 404 if not found. Shipped 2026-05-04. |
| POST | `/api/predict/v1/user/sessions/revoke-others` | low | Revoke all sessions except the current one. Returns `{revokedCount}`. Shipped 2026-05-04. |
| GET, PUT | `/api/predict/v1/user/session-timeouts` | mid | User-configurable session timeout settings. Desktop: 5-240 min (default 60). Terminal: 15-480 min (default 480). Shipped 2026-05-04. |
| GET | `/api/predict/v1/user/dashboard` | mid | |
| GET | `/api/predict/v1/user/activity` | mid | |
| GET | `/api/predict/v1/user/since-last-visit` | mid | |
| POST | `/api/predict/v1/notifications/push/subscribe` | low |
| POST | `/api/predict/v1/notifications/push/unsubscribe` | low |
| GET | `/api/predict/v1/notifications/push/status` | mid |
| GET | `/api/predict/v1/notifications/push/vapid-key` | high |
| POST | `/api/predict/v1/notifications/push/test` | low |
| GET | `/api/predict/v1/notifications` | mid |
| POST | `/api/predict/v1/notifications/read-all` | low |
| POST | `/api/predict/v1/notifications/[id]/read` | mid |
| GET | `/api/predict/v1/notifications/unread-count` | high |

### 4a-1. User offboarding (GDPR-compliant account lifecycle)
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/offboarding/summary` | mid | Pre-offboarding state summary. Returns open positions, running algorithms, credits, data counts, subscription status, pending request, org ownership. Shipped 2026-05-06. |
| POST | `/api/predict/v1/offboarding/clean-exit` | low | Close all positions + stop all algorithms. Uses `panicKill({ all: true })`. Returns `{positionsClosed, algorithmsStopped, creditsReleased, warnings}`. Shipped 2026-05-06. |
| POST | `/api/predict/v1/offboarding/export` | low | Generate GDPR data export. Creates ZIP with all user data tables, uploads to S3. Returns `{exportId, downloadUrl, fileSizeBytes, expiresAt, tablesExported, recordCounts}`. Link valid 24h, file deleted after 7 days. Shipped 2026-05-06. |
| POST | `/api/predict/v1/offboarding/deactivate` | low | Deactivate account (reversible). Executes clean exit, sets `account_status='deactivated'`. Auto-reactivates on next login. Body: `{reason?}`. Shipped 2026-05-06. |
| POST | `/api/predict/v1/offboarding/delete` | low | Schedule account deletion with grace period. Body: `{confirmText: "DELETE MY ACCOUNT", gracePeriodDays?: 7-90}`. Blocks if sole org owner or has live positions. Returns `{requestId, scheduledDeletionAt, gracePeriodDays}`. Migration 180. Shipped 2026-05-06. |
| POST | `/api/predict/v1/offboarding/cancel` | low | Cancel pending deletion. Restores `account_status='active'`. Returns 404 if no pending request. Shipped 2026-05-06. |

### 4b. Broker integration (user-scoped, live-mode triple-gated)
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/user/brokers` | mid | Lists connected brokers + execution mode |
| POST | `/api/predict/v1/user/brokers/test` | low | Test credentials before saving (API key brokers) |
| POST, DELETE | `/api/predict/v1/user/brokers/[brokerId]` | low | Configure (paper only), delete |
| PUT | `/api/predict/v1/user/brokers/[brokerId]` | low | Test saved credentials (ping broker) |
| PATCH | `/api/predict/v1/user/brokers/[brokerId]/mode` | low | Switch paper↔live (3-gate check) |
| PATCH | `/api/predict/v1/user/brokers/[brokerId]/live-ack` | low | MFA acknowledgement toggle |
| GET | `/api/predict/v1/user/brokers/[brokerId]/go-live-eligibility` | mid | Check if user can switch to live |
| POST | `/api/predict/v1/user/brokers/[brokerId]/go-live` | low | MFA-verified live mode switch |
| POST | `/api/predict/v1/user/brokers/pepperstone/oauth/initiate` | low | Start Pepperstone OAuth flow (returns auth URL). Shipped 2026-05-07. |
| GET | `/api/predict/v1/user/brokers/pepperstone/oauth/callback` | public | Handle cTrader OAuth redirect (exchanges code for tokens). Shipped 2026-05-07. |
| POST | `/api/predict/v1/user/brokers/schwab/oauth/initiate` | low | Start Schwab OAuth flow (returns auth URL). Shipped 2026-05-08. |
| GET | `/api/predict/v1/user/brokers/schwab/oauth/callback` | public | Handle Schwab OAuth redirect (exchanges code for tokens). Shipped 2026-05-08. |

**OAuth Brokers (2026-05-08):** Pepperstone (cTrader) and Charles Schwab use OAuth 2.0 instead of API key/secret. Users click "Connect" → redirect to broker → authorize → redirect back. Tokens auto-refresh via scheduler job. **Schwab has a 7-day hard refresh token limit** — users must re-authenticate weekly. See `docs/55-pepperstone-broker-integration.md` and `docs/56-schwab-broker-integration.md`.

### 4c. Webhooks + workflows + triggers (user-scoped)
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/user/webhooks` | mid |
| GET, PUT, DELETE | `/api/predict/v1/user/webhooks/[id]` | mid |
| POST | `/api/predict/v1/user/webhooks/[id]/test` | low |
| POST | `/api/predict/v1/user/webhooks/[id]/rotate-secret` | low |
| GET, POST | `/api/predict/v1/user/workflows` | mid |
| GET, PUT, DELETE | `/api/predict/v1/user/workflows/[id]` | mid |
| POST | `/api/predict/v1/user/workflows/[id]/test` | low |
| GET | `/api/predict/v1/user/workflows/[id]/runs` | mid |
| GET | `/api/predict/v1/user/workflows/[id]/runs/[runId]` | mid |
| POST | `/api/predict/v1/user/workflows/[id]/replay/[runId]` | low |
| GET | `/api/predict/v1/user/workflows/templates` | high |
| POST | `/api/predict/v1/user/workflows/from-template` | low |
| POST | `/api/predict/v1/user/workflows/validate-condition` | mid |
| GET, POST | `/api/predict/v1/user/social-follows` | mid |
| GET, PUT, DELETE | `/api/predict/v1/user/social-follows/[id]` | mid |
| PATCH | `/api/predict/v1/user/social-follows/[id]/credentials` | low |
| POST | `/api/predict/v1/user/social-follows/[id]/poll\|toggle` | low |
| GET | `/api/predict/v1/user/social-follows/[id]/posts` | mid |
| GET, POST | `/api/predict/v1/triggers` | mid |
| GET, PUT, DELETE | `/api/predict/v1/triggers/[triggerId]` | mid |
| GET | `/api/predict/v1/triggers/[triggerId]/events` | mid |
| POST | `/api/predict/v1/triggers/[triggerId]/test\|toggle` | low |

### 4c-1. Alert Triggers API — Shipped 2026-05-01

Database-backed alert triggers with multi-channel delivery. Triggers survive server restarts and deployments.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/triggers` | mid | List user's triggers. Returns `{triggers: TriggerConfig[]}`. |
| POST | `/api/predict/v1/triggers` | mid | Create trigger. Body: `{name, description?, type, provider, config, filters, rateLimit?, enabled?}`. |
| GET | `/api/predict/v1/triggers/[triggerId]` | mid | Get trigger by ID. Returns `{trigger: TriggerConfig}`. |
| PUT | `/api/predict/v1/triggers/[triggerId]` | mid | Update trigger. Body: partial TriggerConfig. |
| DELETE | `/api/predict/v1/triggers/[triggerId]` | mid | Delete trigger and all associated events. |
| GET | `/api/predict/v1/triggers/[triggerId]/events` | mid | Get trigger execution history (last 50). Returns `{events: TriggerEvent[]}`. |
| POST | `/api/predict/v1/triggers/[triggerId]/test` | low | Send test notification. Returns `{event: TriggerEvent}`. |
| POST | `/api/predict/v1/triggers/[triggerId]/toggle` | low | Toggle enabled state. Returns updated trigger. |

**Providers (outbound messaging only):**
- `azure-graph` — Microsoft 365 email via Graph API
- `sendgrid` — SendGrid transactional email
- `resend` — Resend email
- `slack-webhook` — Slack incoming webhook
- `teams-webhook` — Microsoft Teams webhook
- `discord-webhook` — Discord webhook
- `custom-webhook` — Generic HTTPS POST (bearer/api-key/basic auth)
- `twilio` — SMS (scaffolded, requires credentials)
- `firebase-fcm` — Push notifications

**Filters:**
- `severities[]` — Alert severities to match (`critical`, `warning`, `info`)
- `categories[]` — Alert categories (`price`, `sentiment`, `correlation`, `anomaly`, etc.)
- `seriesIds[]` — Optional symbol filter
- `minConfidence` — Minimum confidence threshold (0-1)

**Rate limiting:** Per-trigger `maxPerHour` and `maxPerDay` with automatic counter reset.

**Database tables (Migration 153):**
- `predict.user_triggers` — Trigger configurations
- `predict.trigger_events` — Execution history with status/error
- `predict.trigger_rate_limits` — Per-trigger rate limit counters

**UI:** Settings → Triggers (`/settings/triggers`)

### 4c-1a. Social Follows API — Updated 2026-05-06

Monitor social sources for sentiment signals. Supports 7 platforms: Reddit, Twitter/X, Telegram, Discord, Bluesky, Truth Social, and RSS feeds. Per-user follows are private; admin-configured global follows drive platform-wide sentiment.

See `docs/48-social-follows-and-telegram.md` for full implementation details.

**User Endpoints (Personal Follows):**

| Method | Path | Auth | Rate | Notes |
|--------|------|------|------|-------|
| GET | `/api/predict/v1/user/social-follows` | bearer | mid | List user's follows + platform availability |
| POST | `/api/predict/v1/user/social-follows` | bearer | mid | Create follow. Body: `{platform, followType, handle, category?, pollIntervalMinutes?, botToken?}` |
| DELETE | `/api/predict/v1/user/social-follows/[id]` | bearer | mid | Delete follow (posts remain) |
| PUT | `/api/predict/v1/user/social-follows/[id]/toggle` | bearer | low | Toggle enabled state |
| PATCH | `/api/predict/v1/user/social-follows/[id]/credentials` | bearer | low | Update bot token. Body: `{botToken?}` for Telegram, `{discordToken?}` for Discord |
| POST | `/api/predict/v1/user/social-follows/[id]/poll` | bearer | low | Manually trigger poll |
| GET | `/api/predict/v1/user/social-follows/[id]/posts` | bearer | mid | List ingested posts with sentiment |

**Admin Endpoints (Global Follows):**

| Method | Path | Auth | Rate | Notes |
|--------|------|------|------|-------|
| GET | `/api/predict/v1/admin/social-follows` | bearer+admin | mid | List global follows + platform availability |
| POST | `/api/predict/v1/admin/social-follows` | bearer+admin | mid | Create global follow. Body same as user |
| DELETE | `/api/predict/v1/admin/social-follows/[id]` | bearer+admin | mid | Delete global follow |
| PUT | `/api/predict/v1/admin/social-follows/[id]/toggle` | bearer+admin | low | Toggle enabled state |
| PATCH | `/api/predict/v1/admin/social-follows/[id]/credentials` | bearer+admin | low | Update bot token |
| POST | `/api/predict/v1/admin/social-follows/[id]/poll` | bearer+admin | low | Manually trigger poll |
| GET | `/api/predict/v1/admin/social-follows/[id]/posts` | bearer+admin | mid | List ingested posts |

**Platforms:**
- `reddit` — Subreddits or user feeds (public API, no key required)
- `twitter` — User timelines (requires `TWITTER_BEARER_TOKEN` or falls back to syndication feed)
- `telegram` — Public channels (keyless) or private groups (requires user-provided bot token)
- `discord` — Channels (requires `DISCORD_BOT_TOKEN` or user-provided token)
- `bluesky` — User feeds (public API)
- `truth_social` — User feeds (HTML scrape)
- `rss` — Any valid RSS/Atom feed URL

**Database (Migrations 034, 047, 051, 174):**
- `predict.social_follows` — Follow configurations with encrypted credentials
- `predict.social_posts` — Ingested posts with sentiment
- `predict.sentiment_hourly` — Aggregated sentiment by topic/platform

**UI:**
- User: Settings → Social Follows (`/settings/social-follows`)
- Admin: Admin → Flow (`/admin/flow`)

### 4c-2. Transaction Costs API — Shipped 2026-05-05

User-tunable transaction costs anchored to real broker fee structures. Allows users to configure costs matching their actual broker fees for accurate backtest and AI trading cost estimation.

| Method | Path | Auth | Rate | Notes |
|--------|------|------|------|-------|
| GET | `/api/predict/v1/user/transaction-costs` | bearer | mid | User's cost settings + effective merged costs |
| PUT | `/api/predict/v1/user/transaction-costs` | bearer | low | Update cost settings (template or custom) |
| GET | `/api/predict/v1/transaction-costs/templates` | public | high | Broker fee templates (Alpaca, IBKR, Binance) |
| GET | `/api/predict/v1/transaction-costs/dex` | public | high | DEX fee templates (Uniswap, Curve, PancakeSwap). Query: `?network=eth` |
| GET | `/api/predict/v1/transaction-costs/bridges` | public | high | Bridge fees (Stargate, Hop, Wormhole). Query: `?from=eth&to=arbitrum` |
| GET | `/api/predict/v1/transaction-costs/withdrawals` | public | high | Exchange withdrawal fees. Query: `?exchange=binance&asset=ETH` |
| POST | `/api/predict/v1/transaction-costs/estimate` | bearer | mid | Estimate cost breakdown for a trade |

**Broker Templates (Migration 172):**
- Alpaca: Commission-free equity, 0.25% crypto spread
- IBKR: Lite (free), Pro Tiered ($0.0035/share), Pro Fixed ($0.005/share)
- Binance: VIP0 (0.1%/0.1%), VIP1 (0.09%/0.1%), VIP2 (0.08%/0.1%)

**Crypto Gas/Network Fees:**
- Ethereum: ~$5-50/tx (variable)
- BSC: ~$0.10-0.50/tx
- Polygon: ~$0.01-0.05/tx
- Arbitrum: ~$0.10-0.50/tx
- Solana: ~$0.00025/tx

**DeFi Fees (Migration 173):**
- DEX swap fees: Uniswap 0.01-1%, SushiSwap 0.30%, Curve 0.04%
- Bridge fees: 0-0.10% + gas
- Exchange withdrawal fees by asset/network (24 assets seeded)
- MEV protection premium: ~0.1% gas surcharge

**Settings:**
- `feeTemplateId` — Select broker template or null for custom
- `cryptoNetwork` — Primary network (exchange/eth/bsc/polygon/arbitrum/solana)
- `slippageModel` — none/fixed/dynamic
- `backtestCostMultiplier` — 0.5-3.0x safety buffer

**Database tables:**
- `trading.broker_fee_templates` — Pre-configured real broker fees
- `trading.user_transaction_costs` — User settings + custom overrides
- `trading.user_effective_costs` (VIEW) — Merged template + custom values
- `trading.dex_fee_templates` — DEX protocols by network
- `trading.bridge_fee_templates` — Cross-chain bridges
- `trading.exchange_withdrawal_fees` — Per-asset withdrawal fees

**UI:** Settings → Transaction Costs (`/settings/transaction-costs`)

### 4c-3. Trading Discipline API — Shipped 2026-05-05

Pre-commitment contracts, cool-down periods, trading journal, and performance reviews to help users maintain trading discipline.

| Method | Path | Auth | Rate | Notes |
|--------|------|------|------|-------|
| GET, PUT | `/api/predict/v1/user/discipline/settings` | bearer | mid | Discipline settings (journal enabled, etc.) |
| GET, POST | `/api/predict/v1/user/discipline/contracts` | bearer | mid | Pre-commitment contracts |
| GET, PUT, DELETE | `/api/predict/v1/user/discipline/contracts/[id]` | bearer | mid | Manage specific contract |
| GET, POST | `/api/predict/v1/user/discipline/journal` | bearer | mid | Trading journal entries |
| GET, PUT, DELETE | `/api/predict/v1/user/discipline/journal/[id]` | bearer | mid | Manage journal entry |
| GET | `/api/predict/v1/user/discipline/cooldowns` | bearer | mid | Active cool-down periods |
| POST | `/api/predict/v1/user/discipline/cooldowns/[id]/end` | bearer | low | End cool-down early (with reason) |
| GET, POST | `/api/predict/v1/user/discipline/reviews` | bearer | mid | Performance reviews |
| GET | `/api/predict/v1/user/discipline/reviews/[id]` | bearer | mid | Specific review |
| POST | `/api/predict/v1/user/discipline/reviews/[id]/insights` | bearer | low | Add insights to review |
| POST | `/api/predict/v1/user/discipline/check-trade` | bearer | mid | Check if trade is allowed |

**Contract Types:**
- `daily_trade_limit` — Max trades per day
- `loss_limit` — Max loss before cool-down triggers
- `blocked_hours` — Trading restricted during certain hours
- `position_size` — Max position size rules

**Database tables (Migration 170):**
- `trading.user_discipline_settings` — User settings
- `trading.precommitment_contracts` — Active contracts
- `trading.journal_entries` — Trade journal with emotional state
- `trading.cooldown_periods` — Enforced pause periods
- `trading.discipline_violations` — Contract breaches
- `trading.discipline_reviews` — Weekly/monthly reviews

**UI:** Settings → Trading Discipline (`/settings/discipline`)

### 4c-4. Platform Status API — Shipped 2026-05-05

Platform health monitoring, incident tracking, and user API key alerts.

| Method | Path | Auth | Rate | Notes |
|--------|------|------|------|-------|
| GET | `/api/predict/v1/status` | public | high | Platform status summary |
| GET | `/api/predict/v1/user/connections` | bearer | mid | User's broker/API key status |
| GET | `/api/predict/v1/user/alerts` | bearer | mid | User's pending alerts |
| PUT | `/api/predict/v1/user/alerts/[id]/acknowledge` | bearer | low | Acknowledge an alert |
| GET | `/api/predict/v1/admin/status/health-checks` | bearer+admin | mid | All health check history |
| GET, POST | `/api/predict/v1/admin/status/incidents` | bearer+admin | mid | Active/past incidents |
| PUT | `/api/predict/v1/admin/status/incidents/[id]` | bearer+admin | low | Update incident status |
| GET | `/api/predict/v1/admin/status/alerts` | bearer+admin | mid | Platform-wide alerts |

**Database tables (Migration 171):**
- `predict.platform_health_checks` — Health check history
- `predict.platform_incidents` — Outage tracking
- `predict.user_api_key_alerts` — Expiring/expired key alerts
- `predict.admin_platform_alerts` — Platform-wide issues
- `predict.user_alert_preferences` — Notification preferences

**UI:** Status Page (`/status`)

### 4d. Org-scoped billing (Phase 9 — billing admin only for writes)
| Method | Path | Rate |
|---|---|---|
| GET | `/api/predict/v1/org/billing` | mid |
| POST | `/api/predict/v1/org/billing/checkout` | low |
| PATCH | `/api/predict/v1/org/billing/seats` | low |
| PATCH | `/api/predict/v1/org/billing/admin` | low |

### 4d-1. Org-scoped team management — Shipped 2026-04-28
Auth tier is "team admin" — satisfied by any of: platform admin
(`administrator`/`super_admin`), org billing admin
(`predict.organizations.billing_admin_user_id = caller`), or member
promoted to `auth.users.team_role='admin'`. Platform admins may target
any org via `?orgId=`; billing/team admins are scoped to their own org.
Some endpoints require billing-admin specifically (marked below). The
`by-token` and `accept` invite endpoints have their own auth model —
see notes.

| Method | Path | Auth | Rate | Notes |
|---|---|---|---|---|
| GET | `/api/predict/v1/org/team/members` | team admin | mid | Lists members with `teamRole`, `isBillingAdmin`, `joinedAt`, `lastLoginAt`. |
| DELETE | `/api/predict/v1/org/team/members/[memberId]` | team admin | low | Doesn't delete the user — moves them to a fresh personal workspace. Cannot remove billing admin or self. |
| POST | `/api/predict/v1/org/team/members/[memberId]/suspend` | team admin | low | Body: `{ reason?: string }`. Cannot suspend billing admin or self. |
| POST | `/api/predict/v1/org/team/members/[memberId]/unsuspend` | team admin | low | |
| PATCH | `/api/predict/v1/org/team/members/[memberId]/team-role` | **billing admin** | low | Body: `{ teamRole: 'admin'\|'member' }`. Promote / demote a team admin. |
| GET | `/api/predict/v1/org/team/invites` | team admin | mid | Pending + history. Lazily flips expired-but-pending rows. |
| POST | `/api/predict/v1/org/team/invites` | team admin | low | Body: `{ email, role }`. Sends branded email via the templated `renderOrgInviteEmail`; returns `acceptUrl` for copy-paste fallback. Idempotent on `(orgId,email)` pending. |
| POST | `/api/predict/v1/org/team/invites/bulk` | team admin | low | Body: `{ invites: [{ email, role? }, …] }` (1–100 rows). Returns per-row results + summary (sent / already_member / duplicate_pending / error). |
| DELETE | `/api/predict/v1/org/team/invites/[inviteId]` | team admin | low | |
| GET | `/api/predict/v1/org/team/invites/by-token?token=…` | **public** | high | Token is the capability. Returns org name + inviter for the accept-invite landing. |
| POST | `/api/predict/v1/org/team/invites/accept` | bearer | low | Body: `{ token }`. Email of authed user must match invite email. Atomically flips `organization_id` + `organization_joined_at`, only upgrades `role` from `viewer`/`console_user`. Fires an `ADMIN_ACTION` notification to the inviter. |
| GET | `/api/predict/v1/org/team/domains` | team admin | mid | Lists email-domain claims (`pending\|verified\|rejected`). |
| POST | `/api/predict/v1/org/team/domains` | **billing admin** | low | Body: `{ domain }`. Free-mail domains rejected. Stays `pending` until a platform admin verifies. |
| DELETE | `/api/predict/v1/org/team/domains/[id]` | **billing admin** | low | Removes the claim. Existing members keep their access; only stops future auto-join. |
| GET | `/api/predict/v1/admin/org-domains` | platform admin | mid | Cross-org list of pending claims. |
| POST | `/api/predict/v1/admin/org-domains/[id]` | platform admin | low | Body: `{ action: 'verify'\|'reject', rejectionReason? }`. Verifying flips `status` to `verified` and enables auto-join via `ensurePersonalOrg`. |

### 4e. Personal billing
| Method | Path | Rate |
|---|---|---|
| GET | `/api/predict/v1/billing/subscription` | mid |
| POST | `/api/predict/v1/billing/subscription/cancel` | low |
| POST | `/api/predict/v1/billing/checkout` | low |
| POST | `/api/predict/v1/billing/portal` | low |
| GET | `/api/predict/v1/billing/plans` | high |
| GET | `/api/predict/v1/billing/invoices` | mid |
| GET, POST, DELETE | `/api/predict/v1/billing/payment-methods[/:id]` | mid |
| GET | `/api/predict/v1/billing/usage` | mid |

### 4e-1. AI Credits & BYOK — Shipped 2026-04-30

Three-tier AI billing: **Platform Subscription** (included with tier), **Pay-Per-Use Credits** (top-up balance), **BYOK** (Bring Your Own Key — zero platform cost, validated on save). Credit reservation system prevents overdraft during in-flight LLM calls. Org owners can set member spending caps.

**Credits (user-scoped):**
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/credits` | mid | Current balance, pending reservations, auto-refill config |
| GET | `/api/predict/v1/credits/transactions` | mid | Transaction history. Query: `?limit=50&offset=0&type=purchase\|usage\|refund\|adjustment` |
| GET | `/api/predict/v1/credits/packages` | high | Available credit packages with bonus percentages |
| POST | `/api/predict/v1/credits/purchase` | low | Purchase credits. Body: `{packageId}` or `{amountUsd}` (min $5). Returns Stripe checkout URL. |
| GET | `/api/predict/v1/credits/auto-refill` | mid | Auto-refill settings (threshold, amount, max count before re-auth) |
| PUT | `/api/predict/v1/credits/auto-refill` | low | Update auto-refill. Body: `{enabled, thresholdUsd, refillAmountUsd, maxRefillsBeforeReauth, paymentMethodId}` |
| POST | `/api/predict/v1/credits/estimate` | mid | Estimate cost before LLM call. Body: `{provider, model, estimatedInputTokens, estimatedOutputTokens}`. Returns `{estimatedCredits, estimatedUsd, currentBalance, sufficient}` |

**BYOK (Bring Your Own Key):**
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/byok` | mid | List user's BYOK keys (masked, never raw). Returns `{provider, keyHint, addedAt, lastUsedAt, usageCount}[]` |
| POST | `/api/predict/v1/byok` | low | Add BYOK key. Body: `{provider: 'anthropic'\|'openai'\|'google', apiKey, name?}`. Validates key with provider before saving. AES-256-GCM encrypted. |
| PUT | `/api/predict/v1/byok/[provider]` | low | Update BYOK key (re-validates). Body: `{apiKey, name?}` |
| DELETE | `/api/predict/v1/byok/[provider]` | low | Remove BYOK key |
| POST | `/api/predict/v1/byok/[provider]/validate` | low | Re-validate stored key (checks provider API still accepts) |
| POST | `/api/predict/v1/byok/[provider]/test` | low | Test key with a minimal LLM call (returns latency + model list) |

**AI Billing Config:**
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/ai-billing` | mid | Current billing mode (`subscription`\|`credits`\|`byok`), active providers, fallback chain |
| PUT | `/api/predict/v1/ai-billing` | low | Switch billing mode. Body: `{mode, byokProvider?}`. Validates BYOK keys exist when switching to byok mode, validates credits balance > 0 when switching to credits mode. |
| GET | `/api/predict/v1/ai-billing/usage` | mid | Usage stats by period. Query: `?days=30&groupBy=day\|model\|mode`. Returns tokens, calls, cost breakdown. |
| GET | `/api/predict/v1/ai-billing/credits/packages` | mid | List available credit packages for purchase. Returns `{id, name, displayName, amountCents, priceCents, bonusCents, bonusPercent, popular}[]` |
| POST | `/api/predict/v1/ai-billing/credits/checkout` | low | Create checkout session for credit purchase. Body: `{packageId}`. Returns checkout URL. Requires License Server integration. |
| GET | `/api/predict/v1/ai-billing/credits/transactions` | mid | Credit transaction history. Query: `?limit=50&offset=0`. Returns `{id, type, amountCents, balanceAfterCents, model, description, createdAt}[]` |
| PUT | `/api/predict/v1/ai-billing/credits/auto-refill` | low | Configure auto-refill. Body: `{enabled, thresholdCents?}`. Returns updated auto-refill settings. |
| GET | `/api/predict/v1/ai-billing/byok` | mid | List user's BYOK keys (masked). Returns `{id, provider, keyLast4, label, isValid, lastUsedAt, lastValidatedAt, createdAt, totalRequests}[]` |
| POST | `/api/predict/v1/ai-billing/byok` | low | Add BYOK key. Body: `{provider: 'anthropic'\|'openai', apiKey, label?}`. Validates key before saving. AES-256-GCM encrypted. |
| DELETE | `/api/predict/v1/ai-billing/byok/[id]` | low | Remove BYOK key by ID |
| POST | `/api/predict/v1/ai-billing/byok/[id]/validate` | low | Re-validate stored BYOK key. Returns `{isValid}` |

**Org AI Limits (billing admin):**
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/org/ai-limits` | mid | Org-wide AI spending limits. Returns `{dailyLimitPerMemberUsd, monthlyOrgLimitUsd, alertThresholdPercent}` |
| PUT | `/api/predict/v1/org/ai-limits` | low | Update org limits. **Billing admin only.** |
| GET | `/api/predict/v1/org/ai-limits/usage` | mid | Org-wide AI usage. Returns member breakdown, daily/monthly totals, projections |
| GET | `/api/predict/v1/org/ai-limits/member/[userId]` | mid | Single member's AI usage |
| PUT | `/api/predict/v1/org/ai-limits/member/[userId]` | low | Override member's daily limit. **Billing admin only.** Body: `{dailyLimitUsd}` |

**Schemas:**
- `billing.user_ai_billing` — per-user billing mode + preferences
- `billing.ai_credits` — credit balance + pending reservations
- `billing.ai_credit_transactions` — full audit trail (purchase, usage, refund, adjustment)
- `billing.credit_packages` — admin-defined packages with bonus percentages
- `billing.org_ai_limits` — org-level spending caps
- `billing.member_ai_daily_usage` — per-member daily tracking (resets UTC midnight)
- `billing.ai_model_pricing` — per-model token costs (admin-managed, not hardcoded)
- `billing.ai_billing_settings` — platform-wide defaults (min top-up, max auto-refills)
- `billing.user_byok_keys` — AES-256-GCM encrypted API keys with per-user derived keys

**Migration:** `db/migrations/147_ai_billing_credits.sql`

### 4f. Trading (user-scoped with portfolio ownership guard)
| Method | Path | Rate |
|---|---|---|
| GET | `/api/predict/v1/trading/credits` | mid |
| POST | `/api/predict/v1/trading/credits` | low |
| GET | `/api/predict/v1/trading/credits/transactions` | mid |
| GET, POST | `/api/predict/v1/trading/portfolios` | mid | The `/trading/setup` wizard now persists user selections for `executionMode` (`mock`\|`paper`\|`live`) and `autonomyLevel` (`manual`\|`semi_autonomous`\|`autonomous`) alongside portfolio name + risk level. The two axes are orthogonal — autonomy maps to `algorithm_runs.mode` + `user_algorithms.self_modify` once a strategy is wired in `/admin/algorithms`. Wizard updated 2026-04-28. |
| GET, PATCH | `/api/predict/v1/trading/portfolios/[id]` | mid |
| POST | `/api/predict/v1/trading/portfolios/[id]/fund\|withdraw` | low |
| GET, POST | `/api/predict/v1/trading/portfolios/[id]/positions` | mid |
| PATCH, DELETE | `/api/predict/v1/trading/portfolios/[id]/positions/[positionId]` | low |
| GET, POST | `/api/predict/v1/trading/portfolios/[id]/orders` | mid |
| DELETE | `/api/predict/v1/trading/portfolios/[id]/orders/[orderId]` | low |
| GET | `/api/predict/v1/trading/portfolios/[id]/trades\|performance` | mid |
| GET | `/api/predict/v1/trading/signals` | high |
| GET | `/api/predict/v1/trading/signals/[id]` | mid |
| POST | `/api/predict/v1/trading/signals/[id]/execute` | low |
| GET | `/api/predict/v1/trading/leaderboard` | mid |
| GET | `/api/predict/v1/trading/market-data/price\|candles\|history\|trending\|sp500` | high |
| GET, POST | `/api/predict/v1/trading/webhooks` | mid |
| GET, PUT, DELETE | `/api/predict/v1/trading/webhooks/[id]` | mid |
| POST | `/api/predict/v1/trading/webhooks/callback` | burst |
| GET | `/api/predict/v1/trading/algorithms` | mid |
| GET | `/api/predict/v1/trading/algorithms/[id]` | mid |
| GET | `/api/predict/v1/trading/ai/analysis\|decisions` | mid |
| POST | `/api/predict/v1/trading/ai/manage` | low |
| GET | `/api/predict/v1/trading/marketing-intelligence` | mid |
| GET, POST | `/api/predict/v1/trades` | mid | GET: Unified trade list. POST: Create new trade (manual, paper, AI-assisted). Shipped 2026-04-20. |
| GET | `/api/predict/v1/trades/[id]` | mid | Single trade details. Shipped 2026-04-20. |
| GET | `/api/predict/v1/trades/calendar` | mid | Trades grouped by date for calendar view. Query: `?from=2026-01-01&to=2026-01-31&timezone=America/New_York`. Shipped 2026-04-26. |
| GET | `/api/predict/v1/trades/analysis/time` | mid | Trading time performance analysis. Returns optimal windows, hourly heatmap, session performance. Query: `?timezone=UTC`. Shipped 2026-04-26. |

### 4g. Algorithm builder (user-scoped; some read endpoints use `requireAuth` not `requireActiveUser`)
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/algorithms` | mid |
| GET, PUT, DELETE | `/api/predict/v1/algorithms/[id]` | mid |
| GET | `/api/predict/v1/algorithms/[id]/versions` | mid |
| GET | `/api/predict/v1/algorithms/[id]/runs` | mid |
| POST | `/api/predict/v1/algorithms/[id]/backtest` | **low** (CPU-heavy) |
| POST | `/api/predict/v1/algorithms/[id]/stress-test` | **low** (CPU-heavy) |
| POST | `/api/predict/v1/algorithms/[id]/critique` | **low** (LLM) |
| POST | `/api/predict/v1/algorithms/[id]/paper` | low | Body fields: `startingEquity` (number), `assetClass` (stock\|crypto\|forex\|index\|commodity\|etf\|futures\|perpetual, default stock), `leverage` (integer 1–125 for perpetual / 1–50 for futures, default 1), `brokerId` (optional override, auto-derived from assetClass). See `docs/50-derivatives-and-shorts.md`. |
| POST | `/api/predict/v1/algorithms/[id]/live` | **low** (4-gate preflight) | Body fields: `startingEquity` (number), `assetClass` (stock\|crypto\|forex\|index\|commodity\|etf\|futures\|perpetual, default stock), `leverage` (integer 1–125 for perpetual / 1–50 for futures, default 1), `brokerId` (optional override, auto-derived from assetClass). See `docs/50-derivatives-and-shorts.md`. |
| POST | `/api/predict/v1/algorithms/[id]/generate-modification` | **low** (LLM) |
| GET | `/api/predict/v1/algorithms/[id]/modifications` | mid |
| POST | `/api/predict/v1/algorithms/modifications/[id]` | low |
| GET, PUT | `/api/predict/v1/algorithms/guardrails[/:id]` | mid |
| POST | `/api/predict/v1/algorithms/panic` | **low** (kills all runs) | Per-user emergency stop. `requireAuth` (any role). Body: `{runId?: string, all?: boolean, reason?: string}` — when `runId` is omitted and `all: true`, halts every active paper + live run for the calling user, flattens open live positions through the broker adapter, and writes layer-L5 audit rows. Returns `{killedRunIds: string[]}`. UI surfaces: sidebar PANIC button (typed-`yes` confirm modal, see `PanicStopAllModal.tsx`), `/trading` Controls tab, `/admin/algorithms` PANIC button. Wired site-wide 2026-04-28. |
| GET, POST | `/api/predict/v1/algorithms/paper-runs/[runId]` | mid |
| DELETE | `/api/predict/v1/algorithms/paper-runs/[runId]` | low | Stop an individual run. Body: `{reason?: string}`. Paper runs close positions at current prices; live runs flatten via broker. Returns `{success: true}`. Shipped 2026-05-04. |
| POST | `/api/predict/v1/algorithms/paper-runs/[runId]/tick` | mid |
| GET | `/api/predict/v1/algorithms/active-runs\|regimes\|primitives` | mid |
| GET | `/api/predict/v1/algorithms/audit/jury\|rejections` | mid |
| GET | `/api/predict/v1/algorithms/audit/eod-critic` | mid | LLM end-of-day critic decisions for the calling user (sign_off / escalate / no_data / error) with linked modification + jury verdict. Shipped 2026-04-27. |
| POST | `/api/predict/v1/algorithms/paper-runs/[runId]/eod-critic` | **low** (LLM) | Force-runs the LLM end-of-day critic against a single run. `?force=true` bypasses the daily idempotency check. 60s per-run cooldown returns 429. Shipped 2026-04-27. |
| GET | `/api/predict/v1/algorithms/backtest-jobs` | mid | List the calling user's backtest jobs (walk-forward + regime-stress). Optional `?algorithmId=` filter. Shipped 2026-04-27. |
| GET, DELETE | `/api/predict/v1/algorithms/backtest-jobs/[jobId]` | mid | GET: job status (queued / running / succeeded / failed / cancelled). DELETE: cancel a queued job (running jobs can't be aborted). Shipped 2026-04-27. |
| POST | `/api/predict/v1/algorithms/translate` | **low** (LLM) |
| POST | `/api/predict/v1/algorithms/import` | low |
| GET, POST | `/api/predict/v1/algorithms/[id]/live-metrics` | mid | Real-time performance metrics. GET: history. POST: record snapshot. Shipped 2026-04-20. |
| GET | `/api/predict/v1/algorithms/live-dashboard` | mid | Multi-algorithm performance dashboard. Shipped 2026-04-20. |
| GET, PUT, POST | `/api/predict/v1/algorithms/[id]/risk-controls` | mid | GET: current risk config. PUT: update. POST: evaluate risk state. Shipped 2026-04-20. |
| GET, POST | `/api/predict/v1/algorithms/[id]/ai-suggestions` | **low** (LLM) | GET: pending suggestions. POST: generate new suggestions. Shipped 2026-04-20. |
| POST, DELETE, PATCH | `/api/predict/v1/algorithms/ai-suggestions/[suggestionId]` | low | POST: apply. DELETE: reject. PATCH: rate (1-5). Shipped 2026-04-20. |
| POST | `/api/predict/v1/algorithms/[id]/walk-forward` | **low** (CPU-heavy) | Walk-forward optimization backtest. Shipped 2026-04-20. |
| POST | `/api/predict/v1/algorithms/[id]/monte-carlo` | **low** (CPU-heavy) | Monte Carlo simulation (1000+ paths). Shipped 2026-04-20. |
| GET | `/api/predict/v1/algorithms/templates` | mid | List strategy templates. Shipped 2026-04-20. |
| GET, POST | `/api/predict/v1/algorithms/templates/[templateId]` | mid | GET: template details. POST: create algorithm from template. Shipped 2026-04-20. |
| GET | `/api/predict/v1/algorithms/leaderboard` | mid | Algorithm rankings by trading performance (Sharpe, return, drawdown). Shipped 2026-04-20. |
| GET | `/api/predict/v1/algorithms/leaderboard/my-rankings` | mid | User's algorithm rankings across periods. Shipped 2026-04-20. |
| POST, DELETE | `/api/predict/v1/algorithms/[id]/leaderboard` | low | POST: opt-in (with anonymous option). DELETE: opt-out. Shipped 2026-04-20. |
| GET, POST, PUT | `/api/predict/v1/algorithms/[id]/graduation` | mid | GET: graduation status. POST: start paper trading. PUT: graduate to live. Shipped 2026-04-20. |
| POST | `/api/predict/v1/algorithms/[id]/graduation/acknowledge` | **low** | MFA-gated risk acknowledgment before graduation. Shipped 2026-04-20. |
| GET | `/api/predict/v1/algorithms/resume-requests` | mid | List pending resume requests for the calling user. Returns `{requests: ResumeRequest[], count: number}`. Resume requests are created when runs are interrupted (server restart) and auto-restart is disabled or max restarts exceeded. Shipped 2026-05-04. |
| POST | `/api/predict/v1/algorithms/resume-requests/[id]/approve` | low | Approve a resume request and restart the algorithm run. Returns `{success: true, runId: string, message: string}`. Shipped 2026-05-04. |
| POST | `/api/predict/v1/algorithms/resume-requests/[id]/reject` | low | Reject a resume request and stop the run permanently. Body: `{reason?: string}`. Returns `{success: true, message: string}`. Shipped 2026-05-04. |
| GET | `/api/predict/v1/algorithms/[id]/allocation` | mid | Current portfolio allocation state, drift metrics, and rebalance suggestions. Returns `{allocation: AllocationState, suggestedTrades: RebalanceTrade[]}`. Shipped 2026-05-05. |
| POST | `/api/predict/v1/algorithms/[id]/rebalance` | low | Manually trigger portfolio rebalancing. Returns `{eventId, trades, success}`. Shipped 2026-05-05. |
| GET | `/api/predict/v1/algorithms/[id]/rebalance-history` | mid | Historical rebalancing events with pagination. Query `?limit=50&offset=0`. Returns `{events: RebalancingEvent[], pagination}`. Shipped 2026-05-05. |
| POST | `/api/predict/v1/algorithms/[id]/portfolio-backtest` | **low** (CPU-heavy) | Multi-symbol portfolio backtest with correlation, concentration, and attribution metrics. Body: `{startDate?, endDate?, startingEquity?, parallel?}`. Returns `PortfolioBacktestResult`. Shipped 2026-05-05. |

### 4h. Predictions / events / markets / sentiment (read-heavy user-scoped)
| Method | Path | Rate |
|---|---|---|
| GET | `/api/predict/v1/events` | high |
| GET | `/api/predict/v1/events/stats` | high |
| GET, PATCH, DELETE | `/api/predict/v1/events/[id]` | mid |
| POST | `/api/predict/v1/events/[id]/explain\|resolve` | low |
| GET | `/api/predict/v1/events/[id]/explanations\|signals\|timeline` | mid |
| GET | `/api/predict/v1/events/[id]/signals/summary` | mid |
| POST | `/api/predict/v1/events/import` | low |
| GET | `/api/predict/v1/markets` + dashboard/categories/platforms/search/arbitrage | mid |
| GET | `/api/predict/v1/markets/kalshi\|metaculus\|predictit[/:id]` | mid |
| GET | `/api/predict/v1/polymarket/[slug]` + track / why-moved / dashboard / markets / movements / categories | mid |
| GET | `/api/predict/v1/sentiment` + bulk/topic/topics/domains/mention/timeseries | mid |
| GET | `/api/predict/v1/sentiment/category/[category]\|domain/[domain]\|reddit/[subreddit]` | mid |
| GET | `/api/predict/v1/sentiment/domain/[domain]/trend` | mid |
| GET | `/api/predict/v1/trust/[eventId]` + quick/compute/flags | mid |
| POST | `/api/predict/v1/trust/[eventId]/compute` | low |
| GET | `/api/predict/v1/trust/flagged\|stats` | mid |
| DELETE | `/api/predict/v1/trust/flags/[flagId]` | low |
| GET | `/api/predict/v1/derivatives` | high |
| GET | `/api/predict/v1/discover` | high |
| GET | `/api/predict/v1/insights/human-automation[/:batch]` | high |
| GET | `/api/predict/v1/insights/human-bot` | high |
| GET | `/api/predict/v1/insights/tick-classification` | mid | Whale/bot classification from trade tape. Params: `symbol`, `assetClass`, `limit`. Crypto via Binance (free), equities via Polygon (key required). |
| GET | `/api/predict/v1/insights/orderbook-imbalance` | mid | L2 order book imbalance. Params: `symbol` or `symbols` (batch, max 10), `levels`. Returns volumeImbalance, pressure, walls. Crypto only (Binance, free). Added 2026-04-20. |
| GET | `/api/predict/v1/overlays/series\|data\|live-data\|analysis\|correlation\|crisis\|episodes\|events\|insight` | high |
| GET | `/api/predict/v1/overlays/surprise-index` | mid | Economic Surprise Index composite score. Returns `{compositeScore, components, componentDetails[], direction, rolling3mAvg, rolling6mAvg}`. Similar to Citi ESI, built from FRED data (NFP, CPI, GDP, Retail, ISM, Housing). Cached 1 hour. Shipped 2026-05-01. |
| GET | `/api/predict/v1/overlays/surprise-index/history` | mid | Historical ESI data. Query: `?days=90` (max 365). Returns `{date, compositeScore, direction}[]`. Shipped 2026-05-01. |
| POST | `/api/predict/v1/overlays/analyze` | **low** (heavy) | AI pattern analysis with LLM-powered narrative. Params: `seriesIds[]`, `timeRange`, `generateMarketing`, `generateTrading`, `riskTolerance`. Returns correlations, anomalies, regime changes, and optionally marketing insights or trading strategies. Added 2026-04-20. |
| GET, POST | `/api/predict/v1/overlays/strategies` | mid | List/save pattern-derived strategies. GET params: `type` (marketing\|trading), `limit`. POST body: `name`, `type`, `patternAnalysis`, `strategyConfig`, `dslCode`, `confidence`. Persists to `overlay_strategies`. Added 2026-04-20. |
| GET, DELETE | `/api/predict/v1/overlays/strategies/[id]` | mid | Get or delete a saved strategy by ID. Added 2026-04-20. |
| POST | `/api/predict/v1/overlays/strategies/[id]/convert` | **low** | Convert saved trading strategy to algorithm. Creates entry in `user_algorithms` with DSL code. Returns `algorithmId`, `algorithmName`. Added 2026-04-20. |
| GET | `/api/predict/v1/watchlist` | high |
| POST, DELETE | `/api/predict/v1/watchlist/[eventId]` | mid |
| GET | `/api/predict/v1/watch/alerts\|correlations\|dashboard\|patterns\|signals` | mid |
| GET | `/api/predict/v1/watch/event/[eventId]` | mid |
| GET | `/api/predict/v1/watch/alerts/acknowledged` | mid | **bearer+active**. Returns user's acknowledged alert IDs. Added 2026-04-25. |
| POST | `/api/predict/v1/watch/alerts/acknowledge` | mid | **bearer+active**. Acknowledge an alert (persists across sessions). Body: `alertId`, `alertType`, `alertSeverity`, `alertTitle?`, `notes?`. Added 2026-04-25. |
| GET, PUT | `/api/predict/v1/watch/config` | mid | **bearer+active**. User's watch configuration (selected series, thresholds, notification prefs). PUT body: `seriesIds[]`, `alertTypes[]`, `correlationThreshold`, `anomalyZScore`, `patternSimilarity`, `refreshIntervalMinutes`, `emailAlertsEnabled`, `pushAlertsEnabled`. Added 2026-04-25. |
| GET | `/api/predict/v1/watch/series/available` | mid | **bearer+active**. Returns all available series grouped by category for config modal. Added 2026-04-25. |

### 4i. Community predictions
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/user-predictions` | mid |
| GET, PATCH, DELETE | `/api/predict/v1/user-predictions/[id]` | mid |
| POST | `/api/predict/v1/user-predictions/[id]/cancel\|resolve\|vote` | low |
| GET, POST | `/api/predict/v1/user-predictions/[id]/comments` | mid |
| PATCH, DELETE | `/api/predict/v1/user-predictions/[id]/comments/[commentId]` | low |
| GET | `/api/predict/v1/user-predictions/feed\|leaderboard\|stats` | high |
| GET | `/api/predict/v1/user-predictions/stats/[userId]\|profile/[userId]\|badges/[userId]` | mid |
| POST, DELETE | `/api/predict/v1/user-predictions/follow/[userId]` | low |

### 4j. Marketing analytics (user + org-scoped)
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/marketing/campaigns` | mid |
| GET, PATCH, DELETE | `/api/predict/v1/marketing/campaigns/[id]` | mid |
| GET | `/api/predict/v1/marketing/campaigns/[id]/results` | mid |
| GET | `/api/predict/v1/marketing/accuracy\|attribution\|benchmarks\|channels\|dashboard\|geo\|regions\|seasonal\|signals\|timing\|timing/best\|verticals` | mid |
| POST | `/api/predict/v1/marketing/budget/optimize` | **low** (heavy) |
| POST | `/api/predict/v1/marketing/campaign/predict` | **low** (heavy) |
| GET, POST, DELETE | `/api/predict/v1/marketing/connections[/:id]` | mid |
| POST | `/api/predict/v1/marketing/oauth/initiate` | low |
| GET | `/api/predict/v1/marketing/oauth/callback/[platform]` | low |
| GET | `/api/predict/v1/marketing/platforms[/:platform]\|status\|tiktok\|linkedin\|pinterest` | mid |
| GET, POST | `/api/predict/v1/marketing/predictions[/:generate\|batch]` | **low** (heavy) |
| POST | `/api/predict/v1/marketing/sync` | low |
| GET, POST | `/api/predict/v1/marketing/learning/cycle` | **admin** |

### 4j-1. Campaign Watch (bearer+active) — Shipped 2026-04-26

Competitor campaign intelligence for tracking digital advertising across Meta, Google, TikTok, LinkedIn. **Bidirectional value exchange**: trading signals from campaign launches + marketing insights from market feedback.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/marketing/campaign-watch/advertisers` | mid | List watched competitors |
| POST | `/api/predict/v1/marketing/campaign-watch/advertisers` | low | Add competitor. Body: `{name, ticker?, industry?, metaPageId?, alertOnNewCampaign?}` |
| PUT | `/api/predict/v1/marketing/campaign-watch/advertisers/[id]` | low | Update competitor |
| DELETE | `/api/predict/v1/marketing/campaign-watch/advertisers/[id]` | low | Remove competitor |
| POST | `/api/predict/v1/marketing/campaign-watch/advertisers/[id]/sync` | low | Sync campaigns for single advertiser |
| GET | `/api/predict/v1/marketing/campaign-watch/advertisers/[id]/sightings` | mid | Get advertiser's campaign sightings. Query: `?platform=meta&activeOnly=true` |
| POST | `/api/predict/v1/marketing/campaign-watch/sync` | low | Sync all user's watched advertisers |
| GET | `/api/predict/v1/marketing/campaign-watch/feed` | mid | User's campaign feed. Query: `?platform=meta&activeOnly=true&limit=50&offset=0` |
| GET | `/api/predict/v1/marketing/campaign-watch/search` | mid | Search ads by keyword. Query: `?q=keyword&countries=US,GB&limit=50` |
| GET | `/api/predict/v1/marketing/campaign-watch/alerts` | mid | Get unread campaign alerts |
| POST | `/api/predict/v1/marketing/campaign-watch/alerts/[id]/read` | low | Mark alert as read |
| GET | `/api/predict/v1/marketing/campaign-watch/status` | mid | Integration status (Meta, Google, TikTok, LinkedIn) |
| GET | `/api/predict/v1/marketing/campaign-watch/insights/traders` | mid | Trading signals from campaign activity. Returns alerts + market analyses for tickers |
| GET | `/api/predict/v1/marketing/campaign-watch/insights/marketers` | mid | Marketing insights. Returns competitive benchmarks, platform trends, spend analysis |

**Schemas:**
- `marketing.watched_advertisers` — Companies being tracked with platform IDs
- `marketing.campaign_sightings` — Discovered ads with spend estimates, targeting, creative URLs
- `marketing.campaign_alerts` — New campaign notifications
- `marketing.campaign_intelligence` — Aggregated weekly metrics

**Integrations:**
- Meta Ad Library (free public API) — `META_AD_LIBRARY_ACCESS_TOKEN` or `META_ACCESS_TOKEN`
- Google Ads Transparency (manual lookup) — No API key required

### 4j-bis. Daily-brief system (bearer+active)

Shipped 2026-04-19 across commits 1-5 of the brief sprint, extended through Commit 6 (Slack + TZ save + /settings/verticals + workflow templates + `brief.daily.generated` event), Sprint 3 (honesty pass), 7.6 (dashboard + console display), and 7.7 (PDF export + email attachment). All bearer+active. Each vertical brief is **shared across subscribers** (one row per vertical per day) so per-user fan-out is read-side only. Related user-prefs (TZ + Slack webhook) live in §4a.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET, POST | `/api/predict/v1/verticals` | mid | List user's subscriptions / subscribe to a catalog entry. `attachPdf` (email deliveries) honoured on subscribe. |
| GET | `/api/predict/v1/verticals/catalog` | mid | Browse seeded + public + user's private verticals |
| POST | `/api/predict/v1/verticals/suggest` | **low** (LLM) | Haiku-powered ranker. Falls back to naive if LLM unavailable |
| POST | `/api/predict/v1/verticals/custom` | **low** (LLM) | Opus-powered custom-vertical creation with ticker cite-or-refuse |
| PUT, DELETE | `/api/predict/v1/verticals/[subscriptionId]` | mid | Update send_time / delivery / enabled / attachPdf; unsubscribe |
| GET | `/api/predict/v1/brief` | high | Today's briefs across user's subscriptions |
| GET | `/api/predict/v1/brief/[verticalId]` | high | Single-vertical brief (optional `?date=YYYY-MM-DD`) |
| GET | `/api/predict/v1/brief/[verticalId]/history` | mid | Last N briefs (default 14, max 90) |
| GET | `/api/predict/v1/brief/[verticalId]/pdf` | **low** (pdfkit) | Server-rendered PDF of the brief. `?date=YYYY-MM-DD` optional. `Content-Type: application/pdf`, `Content-Disposition: attachment`, `Cache-Control: private, no-store`. Shipped 7.7 (2026-04-19). |
| POST | `/api/predict/v1/admin/brief/regenerate` | **admin** | Force regen. Body `{ verticalId?, briefDate?, force? }` — supply a `verticalId` for precise single-vertical regen, or omit to run the global job across all subscribed verticals. `force` bypasses inputs_hash skip-recompute. |

### 4k. AI engine (mixed read / admin-gated)
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/ai-engine/accuracy-history\|analytics\|dashboard\|insights\|predictions\|config` | mid | |
| GET, PATCH | `/api/predict/v1/ai-engine/predictions/[predictionId]` | mid | |
| POST | `/api/predict/v1/ai-engine/predictions/[predictionId]/resolve` | low | |
| POST | `/api/predict/v1/ai-engine/auto-resolve\|generate\|seed` | **admin** | |
| GET | `/api/predict/v1/ai-engine/signal-weights` | mid | |
| POST | `/api/predict/v1/ai-engine/signal-weights/cycle` | **admin** | |

### 4l. Backtest (separate from algorithm-builder)
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/backtest` | **low** (CPU) |
| GET, DELETE | `/api/predict/v1/backtest/[resultId]` | mid |
| GET, POST | `/api/predict/v1/backtest/compare` | mid |
| GET, DELETE | `/api/predict/v1/backtest/compare/[comparisonId]` | mid |
| GET | `/api/predict/v1/backtest/dashboard\|templates` | high |
| GET, POST | `/api/predict/v1/backtest/strategies` | mid |
| GET, PATCH, DELETE | `/api/predict/v1/backtest/strategies/[strategyId]` | mid |

### 4m. RAG + analytics + exports
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/rag/query` | low |
| GET | `/api/predict/v1/analytics\|accuracy\|daily\|overview\|sources` | mid |
| GET | `/api/predict/v1/export/ai-engine/pdf\|ai-predictions/csv\|analytics/{csv,pdf}\|predictions/{csv,pdf}\|sources/csv` | **low** (heavy) |
| GET | `/api/predict/v1/export/trades/csv` | **low** | Export user's trades as CSV. **Requires Pro or Enterprise.** History limited by tier (Pro=1yr, Enterprise=unlimited). Filters: source, mode, symbol, dateFrom, dateTo, search. Shipped 2026-04-26. |
| GET | `/api/predict/v1/export/trades/pdf` | **low** | Export user's trades as PDF compliance report. **Requires Enterprise.** Same filters as CSV. Shipped 2026-04-26. |
| GET, POST | `/api/predict/v1/export/scheduled` | mid |
| GET, PATCH, DELETE | `/api/predict/v1/export/scheduled/[reportId]` | mid |
| POST | `/api/predict/v1/export/scheduled/[reportId]/run` | low |

### 4n. Scheduler + feeds + surveillance (some admin)
| Method | Path | Rate |
|---|---|---|
| POST | `/api/predict/v1/scheduler/run\|start\|stop` | **admin** |
| GET | `/api/predict/v1/scheduler/status` | mid |
| GET, POST | `/api/predict/v1/feeds` | mid |
| GET, PATCH, DELETE | `/api/predict/v1/feeds/[id]` | mid |
| POST | `/api/predict/v1/feeds/[id]/run\|toggle` | low |
| GET | `/api/predict/v1/feeds/[id]/runs[/:runId]` | mid |
| GET | `/api/predict/v1/surveillance/[slug]\|dashboard\|risk-summary` | mid |
| GET, POST | `/api/predict/v1/surveillance/[slug]/alerts\|scan` | low |

### 4o. All-seeing-eye (mixed read / admin)
| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/all-seeing-eye/status\|config\|flow` | mid | |
| GET | `/api/predict/v1/all-seeing-eye/insights` | mid | DB-first read (omniscient.unified_insights), in-memory fallback. Updated 2026-04-28. |
| GET | `/api/predict/v1/all-seeing-eye/actions` | mid | DB-first read (omniscient.autonomous_actions), in-memory fallback. Updated 2026-04-28. |
| GET | `/api/predict/v1/all-seeing-eye/black-swan` | mid | Merges in-memory + omniscient.black_swan_warnings + predict.platform_predictions. Updated 2026-04-28. |
| GET | `/api/predict/v1/all-seeing-eye/insights/[id]\|black-swan/[id]` | mid | |
| POST | `/api/predict/v1/all-seeing-eye/insights` | **low** | Body `{action: 'generate'}` — manually triggers `runCycle()`. Same as the cron at § 4o-2. |
| POST | `/api/predict/v1/all-seeing-eye/actions/[id]/approve\|reject` | **admin** | |
| POST | `/api/predict/v1/all-seeing-eye/validation/[id]` | **admin** | |
| GET | `/api/predict/v1/all-seeing-eye/stream/black-swan\|insights` | **SSE** | Long-lived; see § 8 |
| GET | `/api/predict/v1/all-seeing-eye/paradoxes` | mid | Active market paradoxes. Returns paradoxes where market behavior contradicts expected fundamentals. Shipped 2026-05-01. |
| GET | `/api/predict/v1/all-seeing-eye/paradoxes/history` | mid | Historical paradoxes. Query: `?days=7` (max 90). Shipped 2026-05-01. |
| GET | `/api/predict/v1/all-seeing-eye/narratives/latest` | mid | Latest AI-synthesized market narrative (Goldman-quality prose). Returns `{headline, summary, fullAnalysis, keyInsights[], tradingImplications, dataCitations[], confidence}`. Cached 6 hours. Shipped 2026-05-01. |
| GET | `/api/predict/v1/all-seeing-eye/narratives/history` | mid | Historical narratives. Query: `?limit=10` (max 50). Shipped 2026-05-01. |
| POST | `/api/predict/v1/all-seeing-eye/narratives/generate` | **admin, low** | Force regenerate narrative from current paradoxes. Body: `{style?: 'brief'\|'detailed'}`. Requires admin role. Shipped 2026-05-01. |
| GET | `/api/predict/v1/all-seeing-eye/calibration/stats` | mid | Per-rule false positive rates. Returns `{ruleId, totalTriggers, truePositives, falsePositives, pendingOutcome, falsePositiveRate, truePositiveRate, avgLeadTimeDays?}[]`. Shipped 2026-05-04. |
| GET | `/api/predict/v1/all-seeing-eye/calibration/report` | mid | Full calibration report with recommendations. Returns `{generatedAt, totalRules, rulesWithData, overallFPRate, overallTPRate, ruleStats[], recommendations[]}`. Shipped 2026-05-04. |
| GET | `/api/predict/v1/all-seeing-eye/calibration/regime` | mid | Current market regime and thresholds. Returns `{regime: 'post-2023'\|..., thresholds: {sofrSpreadStress, movePanic, hySpreadElevated, vixComplacent, realYieldSpike}}`. Shipped 2026-05-04. |
| POST | `/api/predict/v1/all-seeing-eye/calibration/check-outcomes` | **admin, low** | Manually trigger outcome check for pending triggers. Fetches SPY/VIX data for expired windows and marks triggers as TP/FP. Returns `{checked, truePositives, falsePositives}`. Shipped 2026-05-04. |
| GET | `/api/predict/v1/all-seeing-eye/calibration/crises` | mid | Historical crisis data for backtesting. Returns signal snapshots for 2008 GFC, 2011 Euro Crisis, 2015-16 China/Oil, 2018 Q4, 2019 Repo, 2020 COVID. Shipped 2026-05-04. |
| POST | `/api/predict/v1/all-seeing-eye/calibration/validate` | mid | Validate a threshold against historical crises. Body: `{signal, threshold, operator, crisisId?, phase?}`. Returns `{triggered, actualValue, description}` per crisis. Shipped 2026-05-04. |
| GET | `/api/predict/v1/news/geopolitical/active` | mid | Active geopolitical events with intensity scores. Returns `{eventId, label, articleCount, avgSentiment, intensityScore, affectedAssets}[]`. Shipped 2026-05-01. |
| GET | `/api/predict/v1/news/geopolitical/[eventId]/articles` | mid | Articles tagged with a geopolitical event. Query: `?limit=50&offset=0`. Shipped 2026-05-01. |

**Persistence model (updated 2026-04-28):** All three list endpoints read from `omniscient.*` tables first, fall back to the orchestrator's in-memory caches if the DB query fails or is empty. The orchestrator's `runCycle()` writes through to the same tables (insights → `omniscient.unified_insights`, actions → `omniscient.autonomous_actions`, warnings → `omniscient.black_swan_warnings`). This makes results survive Vercel serverless cold starts — without it the page renders "0 insights" until the next cycle ticks on the same instance.

### 4o-2. All-seeing-eye Cron (Vercel-only, no auth required)
| Method | Path | Schedule | Notes |
|---|---|---|---|
| GET, POST | `/api/cron/all-seeing-eye` | `*/15 * * * *` | Runs `runCycle()` (aggregation → insights → black-swan → actions) and persists output to `omniscient.*`. Auth via `x-vercel-cron: 1` header (Vercel auto-injects) or `Authorization: Bearer ${CRON_SECRET}` for manual triggers. `maxDuration = 300s`. Configured in `apps/web/vercel.json`. Shipped 2026-04-28. |
| GET, POST | `/api/cron/rebalancing-check` | `*/15 * * * *` | Portfolio rebalancing scheduler. Checks algorithms for scheduled rebalancing, detects drift threshold breaches, records portfolio snapshots. Auth via `x-vercel-cron: 1` header or `Authorization: Bearer ${CRON_SECRET}`. `maxDuration = 120s`. Shipped 2026-05-05. |

### 4o-1. Platform Predictions (All-Seeing Eye generated, public)
AI-generated predictions from the All-Seeing Eye that appear in the Terminal Console feed. Each prediction includes a full evidence trail (WHAT, WHY, HOW).

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/platform-predictions` | high | List active platform predictions. Query: `?limit=20&domain=crypto&priority=high`. Returns predictions with evidence trail (title, description, contributing signals, convergence score). Shipped 2026-04-20. |
| GET | `/api/predict/v1/platform-predictions/status` | mid | All-Seeing Eye status + recent insights/warnings count + latest predictions. Shipped 2026-04-20. |
| POST | `/api/predict/v1/platform-predictions/generate` | **low** | Manual trigger for prediction generation. Expires old predictions, generates new from current insights. Requires auth. Shipped 2026-04-20. |

**Schema (predict.platform_predictions):**
```
insight_id, insight_type (ensemble|black-swan|correlation|anomaly), title, description,
domain, direction (up|down|flat|volatile), probability, confidence, convergence_score,
horizon (short|medium|long), priority (low|medium|high|critical), contributing_signals[],
expires_at, status (active|resolved_correct|resolved_incorrect|expired|superseded)
```

**Scheduler:** `platform-predictions` job runs every 15 min — expires old predictions, generates new from All-Seeing Eye insights.

### 4o-2. Price-Action Patterns (user-scoped)
AI-detected price-action patterns (cluster breakout/retest, support bounce, resistance rejection, etc.) with trade suggestions and user subscriptions.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/patterns` | mid | List patterns. Query: `?symbol=BTCUSDT&assetClass=crypto&status=triggered&direction=bullish&limit=50`. Returns patterns with levels, clusters, and trade suggestions. Shipped 2026-04-21. |
| POST | `/api/predict/v1/patterns` | low | Create user-annotated pattern. Body: `{symbol, assetClass, type, direction, levels[], cluster?, notes, tradeSuggestion?}`. Shipped 2026-04-21. |
| GET | `/api/predict/v1/patterns/[id]` | mid | Get pattern details including annotations and trigger events. Shipped 2026-04-21. |
| PUT | `/api/predict/v1/patterns/[id]` | low | Update pattern (status, notes, annotations). Shipped 2026-04-21. |
| DELETE | `/api/predict/v1/patterns/[id]` | low | Delete user-created pattern. AI-detected patterns cannot be deleted. Shipped 2026-04-21. |
| POST | `/api/predict/v1/patterns/detect` | **low** (CPU) | Trigger pattern detection for symbol. Body: `{symbol, assetClass, timeframe?}`. Returns detected patterns. Shipped 2026-04-21. |
| GET | `/api/predict/v1/patterns/active` | high | Get active (forming/triggered) patterns across all symbols. Query: `?assetClass=crypto&minConfidence=0.7`. Shipped 2026-04-21. |
| GET | `/api/predict/v1/patterns/subscriptions` | mid | List user's pattern subscriptions. Shipped 2026-04-21. |
| POST | `/api/predict/v1/patterns/subscriptions` | low | Create subscription. Body: `{symbol?, patternType?, assetClass?, minConfidence?, direction?, channels[]}`. Channels: `email`, `push`, `webhook`, `slack`. Shipped 2026-04-21. |
| DELETE | `/api/predict/v1/patterns/subscriptions/[id]` | low | Delete subscription. Shipped 2026-04-21. |
| GET | `/api/predict/v1/patterns/playbook` | mid | List playbook templates. Query: `?type=cluster_breakout_retest&visibility=public`. Shipped 2026-04-21. |
| POST | `/api/predict/v1/patterns/playbook` | low | Create playbook entry from pattern. Body: `{patternId, name, description, entryRules, exitRules, riskRules, visibility}`. Shipped 2026-04-21. |
| POST | `/api/predict/v1/patterns/playbook/[id]/fork` | low | Fork a public playbook entry. Returns new entry owned by caller. Shipped 2026-04-21. |

#### Expert Enhancement Routes (2026-05-07)

Statistical validation, pattern warming, DTW templates, and emergency controls.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/patterns/stats` | mid | Get historical statistics with confidence intervals. Query: `?type=double_bottom&regime=BULL&direction=bullish`. Returns sampleSize, hitRate, hitRateCI[2], medianMove, moveCI[2], isSignificant, pValue, effectSize. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/stats/recompute` | **low** (CPU) | Recompute pattern statistics. Admin-only. Triggers async recomputation of all pattern stats. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/warming` | high | Get warming (near-trigger) patterns. Query: `?symbols=AAPL,MSFT&minProximity=50&limit=10`. Returns patterns with proximityPct, triggerPrice, regime context, historical hit rates. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/warming/scan` | **low** (CPU) | Trigger warming scan for symbols. Body: `{symbols: string[]}`. Returns warming patterns found. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/significance` | mid | Get significance analysis for pattern type. Query: `?type=support_bounce&direction=bullish&strictMode=true`. Returns isSignificant, shouldAutoTrade, warnings[], recommendation. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/candle-scan` | mid | Scan for candlestick pattern across symbols. Body: `{pattern: string, symbols?: string[], lookbackDays?: number, maxResults?: number, outcomeHorizon?: number}`. Returns matches with entry/current prices, outcome%, win/loss, and stats (totalOccurrences, winRate, avgReturn, bySymbol breakdown). Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/candle-scan/types` | high | Get all 18 candlestick pattern types with metadata. Returns patterns grouped by category (singleBar, twoBar, threeBar) with name, direction, reliability, and bars required. Shipped 2026-05-07. |

**Pattern Hunter (Multi-market scanning with timing analysis):**

| Method | Path | Rate | Notes |
|--------|------|------|-------|
| POST | `/api/predict/v1/patterns/hunter/scan` | **low** (CPU) | Multi-market pattern scan. Body: `{symbols: string[], patternTypes?: string[], minConfidence?: number, assetClass?: string}`. Max 50 symbols. Returns detected patterns with timing analysis, warming patterns, timing insights, scan duration. Shipped 2026-05-08. |
| GET | `/api/predict/v1/patterns/hunter/history` | mid | Fetch detection history with timing stats. Query: `?symbols=AAPL,MSFT&patternTypes=double_bottom&startDate=2026-01-01&endDate=2026-05-08&includeAbnormal=true&limit=100&offset=0`. Returns events[], stats (byPatternType, byHour, abnormalCount, hitRate), pagination. Shipped 2026-05-08. |
| POST | `/api/predict/v1/patterns/hunter/quick-alert` | low | Create alert subscriptions from hunter config. Body: `{symbols: string[], patternTypes?: string[], minConfidence?: number, channels: string[], alertOnForming?, alertOnTriggered?, alertOnConfirmed?}`. Creates subscription per symbol. Auth required. Shipped 2026-05-08. |
| GET | `/api/predict/v1/patterns/hunter/export` | low | Export detection history as CSV. Query params same as `/history`. Returns CSV file download. Auth required. Shipped 2026-05-08. |
| GET | `/api/predict/v1/patterns/hunter/stream` | high (SSE) | SSE stream for real-time pattern updates. Query: `?symbols=AAPL,MSFT&patternTypes=double_bottom`. Emits connected, heartbeat, pattern_detected events. Shipped 2026-05-08. |

| GET | `/api/predict/v1/patterns/templates` | mid | List user's DTW pattern templates. Query: `?limit=50&offset=0`. Returns templates with metadata, match counts, hit rates. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/templates` | low | Create DTW template from chart selection. Body: `{name, symbol, timeframe, startDate, endDate, direction?, patternType?, tags[], minSimilarityPct?}`. Normalizes and stores pattern. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/templates/[id]` | mid | Get template details including normalized series. Shipped 2026-05-07. |
| DELETE | `/api/predict/v1/patterns/templates/[id]` | low | Delete template. Cascade deletes matches. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/templates/[id]/matches` | mid | Get saved matches for template. Query: `?limit=50&minSimilarity=70`. Returns matches with similarity scores, outcomes. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/templates/[id]/matches` | **low** (CPU) | Find new matches for template. Body: `{symbols: string[], startDate?, endDate?, persist?: boolean}`. Uses DTW algorithm with early abandon. Shipped 2026-05-07. |

**User-Defined Candlestick Patterns (Custom pattern builder):**

Create, import, and use custom candlestick patterns with user-defined detection rules. Shipped 2026-05-10.

| Method | Path | Rate | Notes |
|--------|------|------|-------|
| GET | `/api/predict/v1/patterns/user-candle` | mid | List user's candlestick patterns. Query: `?direction=bullish&barCount=2&includeSystem=true&includePublic=true&limit=100&offset=0`. |
| POST | `/api/predict/v1/patterns/user-candle` | low | Create pattern. Body: `{name, description?, direction, reliability?, rules: {bars, trend_context?, trend_lookback?, rules: [barRules], min_pattern_range_pct?, max_pattern_range_pct?}, isPublic?}`. |
| GET | `/api/predict/v1/patterns/user-candle/[id]` | mid | Get pattern details including rules and validation stats. |
| PUT | `/api/predict/v1/patterns/user-candle/[id]` | low | Update pattern. Body: same as create, all fields optional. |
| DELETE | `/api/predict/v1/patterns/user-candle/[id]` | low | Delete pattern (user-owned only, not system patterns). |
| POST | `/api/predict/v1/patterns/user-candle/[id]/fork` | low | Fork pattern (create a copy). Body: `{name?}`. |
| POST | `/api/predict/v1/patterns/user-candle/[id]/validate` | **low** (CPU) | Validate against history. Body: `{symbols?: string[], lookbackDays?: 365, targetBars?: 5, winThresholdPct?: 0}`. Returns hit rate with Wilson CI, avg return. |
| GET | `/api/predict/v1/patterns/user-candle/export` | mid | Export user's pattern library as JSON. Returns `{version: "1.0", exportedAt, patterns[]}`. |
| POST | `/api/predict/v1/patterns/user-candle/import` | low | Import pattern library. Body: `{library: {version, patterns[]}, overwriteExisting?: false}`. Returns `{imported, skipped, errors[]}`. |
| POST | `/api/predict/v1/patterns/user-candle/detect` | mid | Detect patterns for symbol. Body: `{symbol, assetClass?, lookback?: 50, patternIds?: string[]}`. Returns matches with confidence. |

**Pattern Import (User-created patterns with AI validation):**

| Method | Path | Rate | Notes |
|--------|------|------|-------|
| POST | `/api/predict/v1/patterns/import/interpret` | **low** (LLM) | Interpret pattern from various inputs. Body: `{method: 'natural_language'|'image_upload'|'chart_selection'|'dsl', input: {...}}`. Returns AI interpretation with name, rules, trigger conditions, warnings, suggestions, and readback for user confirmation. Uses Claude Vision for image uploads. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/import/confirm` | low | Confirm and save pattern after review. Body: `{method, input, interpretation, modifications?: {name?}}`. Creates user_pattern_template. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/import/natural-language` | **low** (LLM) | Direct natural language import. Body: `{text: string, context?: {preferredTimeframe?, preferredAssetClasses?}}`. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/import/image` | **low** (Vision) | Import from chart screenshot. Body: `{imageBase64: string, mimeType: 'image/jpeg'|'image/png'|'image/webp', context?: string}`. Uses Claude Vision AI to analyze chart. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/import/chart-selection` | low | Import from chart range selection. Body: `{symbol, startDate, endDate, priceData: Array<{date, open, high, low, close, volume}>}`. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/import/dsl` | low | Import direct DSL rules. Body: `{name: string, rules: Array<{type, params}>}`. Validates rule structure. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/import/validate` | mid | Validate pattern against historical data. Body: `{templateId}`. Returns historical hit rate, sample size, confidence intervals. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/import/templates` | mid | List user's imported pattern templates. Query: `?active=true&limit=50`. Returns templates with usage stats. Shipped 2026-05-07. |
| PUT | `/api/predict/v1/patterns/import/templates/[id]` | low | Update imported template. Body: `{name?, rules?, isActive?, alertEnabled?}`. Shipped 2026-05-07. |
| DELETE | `/api/predict/v1/patterns/import/templates/[id]` | low | Delete imported template. Cascade deletes matches. Shipped 2026-05-07. |

**Pattern Playback (Bar-by-bar Learning):**

Replay historical patterns bar-by-bar to learn pattern recognition and validate trading decisions. Shipped 2026-05-07.

| Method | Path | Rate | Notes |
|--------|------|------|-------|
| GET | `/api/predict/v1/patterns/playback` | mid | Get pattern with historical bars for playback. Query: `?random=true&type=double_bottom&outcome=profit`. Returns pattern with bars[], triggerBarIndex, formationStartIndex, formationEndIndex. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/playback?list=true` | mid | List available patterns for playback. Query: `?list=true&type=&outcome=&limit=50`. Returns patterns[] summary and total count. Shipped 2026-05-07. |

**Pattern Timing Analysis (Time-of-Day / Day-of-Week):**

Analyzes when patterns occur to identify optimal timing windows and abnormal firing times. Shipped 2026-05-07.

| Method | Path | Rate | Notes |
|--------|------|------|-------|
| GET | `/api/predict/v1/patterns/timing` | mid | Get comprehensive timing analysis. Query: `?type=double_bottom&symbol=AAPL&lookbackDays=365`. Returns hourlyStats[], dailyStats[], heatmap[], bestHour, worstHour, insights[]. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/timing/heatmap` | mid | Get 24x7 heatmap data. Query: `?type=double_bottom`. Returns cells[] with hour, dayOfWeek, occurrences, hitRate, intensity (0-100). For visual heat grid. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/timing/check` | mid | Check if current timing is abnormal. Query: `?type=double_bottom&hour=14&dayOfWeek=3`. Returns isAbnormal, zscore, confidencePenalty, recommendation. For real-time warnings. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/timing/insights` | mid | Get timing insights and best/worst times. Query: `?type=double_bottom`. Returns insights[], bestTimes[], worstTimes[], summary. Shipped 2026-05-07. |

**Pattern Scheduler (Complex Pattern Rules with Time Windows):**

Visual scheduler for creating complex pattern rules with AND/OR/NOT/THEN logic, timezone-aware time windows, and multi-market support. Desktop-only feature with drag-drop timeline. Shipped 2026-05-07.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/patterns/scheduler/rules` | mid | List user's scheduler rules. Returns rules[] with logic trees, time windows, match counts. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/scheduler/rules` | low | Create scheduler rule. Body: `{name, description?, logicTree, priority?, onMatchActions?, isEnabled?}`. LogicTree is recursive AND/OR/NOT/THEN/XOR structure with pattern and time conditions. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/scheduler/rules/[id]` | mid | Get rule with time windows and slots. Returns rule, slots[]. Shipped 2026-05-07. |
| PUT | `/api/predict/v1/patterns/scheduler/rules/[id]` | low | Update rule. Body: partial rule fields. Shipped 2026-05-07. |
| DELETE | `/api/predict/v1/patterns/scheduler/rules/[id]` | low | Delete rule. Cascade deletes time windows and slots. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/scheduler/rules/[id]/toggle` | low | Toggle rule enabled/disabled. Returns updated rule. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/scheduler/rules/[id]/test` | mid | Test evaluate rule with current market conditions. Returns evaluation tree with match/no-match results, recent patterns used. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/scheduler/time-windows` | low | Create time window for rule. Body: `{ruleId, timezone?, activeHours?, blackoutHours?, activeDays?, marketSessionPreset?, markets?, autoDetectMarkets?, scanDurationMinutes?}`. Shipped 2026-05-07. |
| PUT | `/api/predict/v1/patterns/scheduler/time-windows/[id]` | low | Update time window. Body: partial fields. Shipped 2026-05-07. |
| DELETE | `/api/predict/v1/patterns/scheduler/time-windows/[id]` | low | Delete time window. Cascade deletes slots. Shipped 2026-05-07. |
| POST | `/api/predict/v1/patterns/scheduler/slots` | low | Create schedule slot (pattern on timeline). Body: `{timeWindowId, patternTemplateId?, userPatternTemplateId?, patternType?, startHour, startMinute?, endHour, endMinute?, minConfidence?, directionFilter?, symbols?}`. Shipped 2026-05-07. |
| PUT | `/api/predict/v1/patterns/scheduler/slots/[id]` | low | Update slot timing/config. Body: partial fields. Shipped 2026-05-07. |
| DELETE | `/api/predict/v1/patterns/scheduler/slots/[id]` | low | Delete slot. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/scheduler/presets` | high | List market session presets (NYSE, NASDAQ, LSE, Asian, forex 24/5, crypto 24/7, etc.). Returns presets[] with resolved hours/days/timezone. Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/scheduler/timezones` | high | List available timezones. Returns common[] (UTC, user_local, major cities), markets[] (market timezones). Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/scheduler/pattern-types` | high | List built-in pattern types. Returns builtIn[] (fvg_bullish, double_bottom, etc.). Shipped 2026-05-07. |
| GET | `/api/predict/v1/patterns/scheduler/markets` | high | List available markets for multi-market selection. Returns markets[] with id, name, timezone, hours, asset classes. Shipped 2026-05-07. |

**Schema (trading.pattern_scheduler_rules):**
```
id, user_id, name, description, logic_tree (JSONB: AND/OR/NOT/THEN/XOR operators with pattern/time conditions),
is_enabled, priority (1-10), on_match_actions (JSONB: notify/log/webhook/start_algorithm/paper_trade),
times_matched, last_matched_at, created_at, updated_at
```

**Schema (trading.pattern_time_windows):**
```
id, rule_id, timezone (IANA or 'user_local' or 'UTC'), active_hours[], blackout_hours[], active_days[] (ISO 1-7),
market_session_preset (nyse|nasdaq|lse|asian|london_newyork_overlap|forex_24_5|crypto_24_7|...),
markets (JSONB: [{marketId, isAiSuggested, reason?}]), auto_detect_markets,
scan_duration_minutes, window_order, created_at
```

**Schema (trading.pattern_schedule_slots):**
```
id, time_window_id, pattern_template_id, user_pattern_template_id, pattern_type (built-in),
start_hour (0-23), start_minute, end_hour, end_minute,
min_confidence, direction_filter (bullish|bearish|any), symbols[], slot_config (JSONB), created_at
```

**Schema (trading.pattern_schedule_matches):**
```
id, rule_id, slot_id, symbol, matched_at, local_hour, local_day_of_week,
logic_evaluation (JSONB: full evaluation tree), actions_executed (JSONB),
outcome (profit|loss|breakeven|pending), outcome_at, outcome_pnl_pct
```

**Logic Tree Structure:**
```json
{
  "id": "root",
  "type": "AND",
  "children": [
    {"id": "p1", "type": "PATTERN", "patternType": "double_bottom", "minConfidence": 0.7},
    {"id": "t1", "type": "TIME", "condition": "session_active", "marketId": "nyse"},
    {"id": "seq", "type": "THEN", "children": [
      {"id": "p2", "type": "PATTERN", "patternType": "fvg_bullish"},
      {"id": "p3", "type": "PATTERN", "patternType": "support_bounce"}
    ], "delayMinutes": 60}
  ]
}
```

**Scheduler:** `pattern-schedule-evaluator` job runs every 5 min — evaluates enabled rules against recent patterns and time windows.

**Schema (trading.pattern_timing_events):**
```
id, pattern_id, pattern_type, symbol, asset_class, direction,
detected_hour (0-23), detected_day_of_week (0-6 Sun-Sat), detected_minute, detected_at,
outcome ('hit'|'miss'|'pending'), outcome_pnl_pct,
is_abnormal_timing, timing_zscore, expected_hour_pct, actual_hour_pct
```

**Scheduler:** `pattern-timing-stats` runs nightly — backfills timing events, recomputes aggregated statistics per pattern type.

#### Emergency Kill Switch (2026-05-07)

Hardware-ready emergency stop API for physical kill switches (USB buttons, Raspberry Pi, etc.).

| Method | Path | Rate | Notes |
|---|---|---|---|
| POST | `/api/predict/v1/emergency/kill` | **burst** | Emergency stop all trading. Auth: Bearer OR X-API-Key (hardware). Body: `{hardwareId?, reason?, flattenPositions?: boolean}`. Stops all runs, optionally flattens positions. Target: <100ms response. Shipped 2026-05-07. |
| GET | `/api/predict/v1/emergency/status` | mid | Get kill switch status. Returns killSwitchActive, pausedAt, recentKillEvents[]. Shipped 2026-05-07. |
| POST | `/api/predict/v1/emergency/resume` | low | Resume trading after emergency kill. Resets kill switch flag. Shipped 2026-05-07. |

**Pattern Intelligence (Unified Warming + Hunter with Real-time Streaming):**

Unified pattern intelligence system integrating Pattern Warming Radar and Pattern Hunter with shared watchlist, warming history tracking, cross-references between pattern systems, and real-time SSE streaming to Terminal Console. Shipped 2026-05-08.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/patterns/watchlist` | mid | Get user's shared pattern watchlist. Query: `?limit=50`. Returns symbols shared between Warming Radar and Pattern Hunter. Auth required. Shipped 2026-05-08. |
| POST | `/api/predict/v1/patterns/watchlist` | low | Add symbol to watchlist. Body: `{symbol: string, notes?: string}`. Infers asset class from symbol. Auth required. Shipped 2026-05-08. |
| DELETE | `/api/predict/v1/patterns/watchlist/[symbol]` | low | Remove symbol from watchlist. Auth required. Shipped 2026-05-08. |
| GET | `/api/predict/v1/patterns/warming/history` | mid | Get warming pattern history. Query: `?symbol=AAPL&outcome=triggered&limit=50`. Returns warming detections with outcomes (triggered/fizzled/pending), prices, timestamps. Auth required. Shipped 2026-05-08. |
| GET | `/api/predict/v1/patterns/warming/stats` | mid | Get warming statistics. Query: `?symbol=AAPL`. Returns totalDetected, triggered, fizzled, pending, successRate (%). Auth required. Shipped 2026-05-08. |
| GET | `/api/predict/v1/patterns/cross-references` | mid | Get pattern cross-references. Query: `?symbol=AAPL&symbols=AAPL,MSFT&limit=20&includeExpired=false`. Links Hunter patterns to Warming patterns at same price levels. Public read. Shipped 2026-05-08. |
| GET | `/api/predict/v1/realtime/pattern-intelligence` | high (SSE) | SSE stream for pattern intelligence events. Query: `?symbols=AAPL,MSFT`. Emits: `connected`, `heartbeat`, `PATTERN_WARMING_ALERT`, `PATTERN_HUNTER_DETECTION`, `PATTERN_CROSS_REFERENCE`, `PATTERN_OUTCOME_UPDATE`. Shipped 2026-05-08. |

**Schema (predict.pattern_watchlist):**
```
id, user_id, symbol, asset_class, notes, added_at
UNIQUE(user_id, symbol)
```

**Schema (predict.pattern_warming_history):**
```
id, user_id, symbol, pattern_type, proximity_at_detection, detected_at,
outcome ('triggered'|'fizzled'|'pending'), outcome_at,
price_at_detection, price_at_outcome, metadata (JSONB)
```

**Schema (predict.pattern_cross_references):**
```
id, hunter_pattern_id, warming_pattern_type, symbol,
correlation_score (0-100), detected_at, price_level, description
```

**Scheduler Jobs:**
- `warming-outcome-checker` (hourly): Checks pending warming detections and updates outcomes based on price movement
- `cross-reference-cleanup` (6 hours): Cleans up expired cross-references older than 7 days

---

**AI Stock Hunter (Claude-powered stock research and recommendations):**

Claude-powered stock research system that aggregates fundamentals, technicals, sentiment, and patterns, then generates research-backed trade recommendations with thesis, risk assessment, and data citations. Shipped 2026-05-08.

| Method | Path | Rate | Notes |
|---|---|---|---|
| POST | `/api/predict/v1/stock-hunter/scan` | **low** (LLM) | Trigger stock scan. Body: `{scanType: 'watchlist'|'preset'|'custom', symbols?: string[], preset?: string, runBacktest?: boolean, maxSymbols?: number}`. Max 20 symbols. Returns scanId, scanned count, recommendations[], skipped[], tokensUsed, durationMs. Uses Claude for analysis with cite-or-refuse constraint. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/recommendations` | mid | List active recommendations. Query: `?limit=50&offset=0&symbol=AAPL&direction=long&minConfidence=0.6&includeAll=false`. Returns recommendations[], pagination. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/recommendations/[id]` | mid | Get single recommendation with full thesis, risk assessment, key factors, data citations. Shipped 2026-05-08. |
| DELETE | `/api/predict/v1/stock-hunter/recommendations/[id]` | low | Dismiss recommendation. Sets status to 'dismissed'. Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/recommendations/[id]/backtest` | **low** (CPU) | Run backtest on recommendation. Body: `{days?: number}`. Returns sharpe, returnPct, maxDrawdownPct. Updates recommendation with backtest results. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/presets` | high | Get available scan presets. Returns presets[] with name, displayName, description, symbols, category. **39 presets across 18 categories** including healthcare (pharma, biotech, medical devices), technology (semiconductors, cybersecurity, AI, cloud), financials (banks, fintech, insurance), energy (oil & gas, clean energy), industrials, consumer, communications, international (China/Europe ADRs), and thematic (EV, space, cannabis, water). Admin-configurable via `/admin/stock-hunter`. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/stats` | mid | Get user's hunter stats. Returns totalRecommendations, activeRecommendations, winRate (%), avgConfidence. Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/reports` | **low** (LLM) | Generate comprehensive research report. Body: `{symbol, assetClass?, recommendationId?}`. Returns reportId for polling. Report generated async with 8 sections. Uses BYOK billing. ~$1.08 per report (Opus). Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/reports/generate` | **low** (LLM) | Alias for POST /reports. Same body/response. |
| GET | `/api/predict/v1/stock-hunter/reports` | mid | List user's research reports. Query: `?limit=50&offset=0&status=completed&symbol=AAPL`. Returns reports[], pagination. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/reports/[id]` | mid | Get full research report with all sections, key metrics, data citations, LLM metadata. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/reports/[id]/status` | high | Poll report generation status. Returns status ('pending'|'generating'|'completed'|'failed'), sectionsCompleted, totalSections, currentSection, progressPercent. Poll every 2s. Shipped 2026-05-08. |
| DELETE | `/api/predict/v1/stock-hunter/reports/[id]` | low | Delete a research report. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/reports/estimate` | high | Get cost estimate for report generation. Returns estimatedCostCents (108), estimatedCostDollars ('1.08'), sections (8). Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/scan-history` | mid | Get user's scan history. Query: `?limit=50`. Returns scans[] with id, scanType, symbolCount, recommendationsGenerated, createdAt. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/archived` | mid | Get user's archived recommendations. Query: `?limit=200`. Returns archived recommendations with outcome tracking (hit_target, hit_stop, expired, dismissed). Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/recommendations/[id]/archive` | low | Archive a recommendation. Body: `{reason?, currentPrice?}`. Sets archivedAt, archiveReason, priceAtArchive. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/alerts` | mid | List user's price alerts. Returns alerts[] with status (active/triggered/expired/cancelled). Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/alerts` | low | Create price alert. Body: `{recommendationId?, symbol, alertType, condition, triggerPrice, notifyPush?, notifyEmail?, expiresAt?}`. Shipped 2026-05-08. |
| DELETE | `/api/predict/v1/stock-hunter/alerts/[id]` | low | Delete price alert. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/scheduled-scans` | mid | List user's scheduled scans. Returns scans[] with schedule config and last run info. Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/scheduled-scans` | low | Create scheduled scan. Body: `{name, scanType, presetName?, customSymbols?, scheduleType, scheduleTime, scheduleDays?, timezone?}`. Shipped 2026-05-08. |
| DELETE | `/api/predict/v1/stock-hunter/scheduled-scans/[id]` | low | Delete scheduled scan. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/paper-trades` | mid | List user's paper trades. Query: `?status=open`. Returns trades[] with P&L tracking. Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/paper-trades` | low | Create paper trade from recommendation. Body: `{recommendationId, direction, quantity, entryPrice, targetPrice?, stopLossPrice?}`. Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/paper-trades/[id]/close` | low | Close paper trade. Body: `{exitPrice, exitReason?}`. Calculates realized P&L. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/performance` | mid | Get performance stats. Query: `?period=all_time|ytd|30d|7d`. Returns win/loss counts, win rate, avg returns, profit factor. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/favorite-presets` | mid | List user's favorite presets with display order. Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/favorite-presets` | low | Add preset to favorites. Body: `{presetId}`. Shipped 2026-05-08. |
| DELETE | `/api/predict/v1/stock-hunter/favorite-presets/[id]` | low | Remove preset from favorites. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/market-data/[symbol]` | mid | Get market data for symbol (news, earnings, options flow, insider trades). Uses caching. Shipped 2026-05-08. |
| GET | `/api/predict/v1/stock-hunter/market-data` | mid | Get batch market data. Query: `?symbols=AAPL,MSFT` (max 20). Shipped 2026-05-08. |
| POST | `/api/predict/v1/stock-hunter/quick-trade` | low | Execute quick trade. Body: `{symbol, side, quantity, orderType?, limitPrice?, recommendationId?, usePaper?}`. Routes to paper or live based on user mode. Shipped 2026-05-08. |

**Schema (predict.stock_hunter_recommendations):**
```
id, user_id, symbol, asset_class, direction ('long'|'short'|'neutral'),
recommendation ('strong_buy'|'buy'|'hold'|'sell'|'strong_sell'), confidence (0-1),
current_price, entry_price, target_price, stop_loss_price, risk_reward_ratio,
thesis (AI-generated, 50-1500 chars), risk_assessment (50-800 chars),
key_factors (JSONB: [{factor, impact: 'positive'|'negative'|'neutral', weight}]),
data_citations (JSONB: [{claim, dataPoint, source}]),
fundamentals_summary, technicals_summary, sentiment_summary, patterns_detected, market_context (all JSONB),
llm_model, llm_tokens_used, llm_latency_ms, jury_decision,
backtest_run, backtest_sharpe, backtest_return_pct, backtest_max_drawdown_pct,
status ('active'|'triggered'|'expired'|'executed'|'dismissed'),
expires_at, outcome ('win'|'loss'|'pending'|'expired'), actual_return_pct,
created_at, updated_at
```

**Schema (predict.stock_hunter_scans):**
```
id, user_id, scan_type ('watchlist'|'preset'|'custom'), symbols[], preset_name,
recommendations_generated, recommendations_skipped, total_tokens_used, scan_duration_ms, created_at
```

**Schema (predict.stock_hunter_presets):**
```
id, name (unique slug), display_name, description, symbols[], category,
is_active, sort_order, created_by (admin user), created_at, updated_at
```

**Schema (predict.stock_hunter_research_reports):**
```
id, user_id, recommendation_id (optional FK), symbol, asset_class,
-- 8 report sections (all TEXT, nullable):
executive_summary, company_overview, financial_analysis, technical_analysis,
sentiment_analysis, risk_analysis, competitive_context, price_targets_thesis,
-- Structured data:
key_metrics (JSONB: {peRatio, marketCap, revenueGrowth, entryPrice, targetPrice, ...}),
data_citations (JSONB: [{claim, dataPoint, source, section}]),
-- Generation tracking:
generation_status ('pending'|'generating'|'completed'|'failed'),
sections_completed (0-8), total_sections (8), current_section, error_message,
-- LLM audit:
llm_model, llm_tokens_used, llm_latency_ms, llm_calls_made,
-- Input snapshot:
data_bundle_snapshot (JSONB),
created_at, updated_at, completed_at
```

**Research Report Sections (8 total):**
1. Executive Summary (required) - 200-300 word overview, key thesis
2. Company Overview (stocks/ETFs only) - Business model, competitive position
3. Financial Analysis (stocks/ETFs only) - P/E, growth, margins, debt metrics
4. Technical Analysis (required) - Trend, momentum, support/resistance
5. Sentiment Analysis (when available) - News, social, analyst consensus
6. Risk Analysis (required) - Downside scenarios, specific risks
7. Competitive Context (optional) - Industry position, peer comparison
8. Price Targets & Thesis (required) - Entry/target/stop with rationale

**Report Cost:** ~$1.08 per full 8-section report using Claude Opus (BYOK billing).

**Schema (predict.stock_hunter_price_alerts):**
```
id, user_id, recommendation_id (optional), symbol,
alert_type ('entry'|'target'|'stop_loss'|'custom'), condition ('above'|'below'|'crosses'),
trigger_price, status ('active'|'triggered'|'expired'|'cancelled'),
triggered_at, triggered_price, notify_push, notify_email, expires_at, created_at
```

**Schema (predict.stock_hunter_scheduled_scans):**
```
id, user_id, name, scan_type ('watchlist'|'preset'|'custom'),
preset_name, custom_symbols[], schedule_type ('daily'|'weekly'|'monthly'),
schedule_time, schedule_days[], timezone, is_active,
last_run_at, next_run_at, last_run_status, last_run_count, created_at
```

**Schema (predict.stock_hunter_paper_trades):**
```
id, user_id, recommendation_id (optional), symbol, direction ('long'|'short'),
entry_price, quantity, position_size_usd, target_price, stop_loss_price,
status ('open'|'closed'|'stopped_out'), exit_price, exit_reason,
unrealized_pnl, realized_pnl, pnl_percent, opened_at, closed_at,
current_price, high_since_entry, low_since_entry, last_price_update
```

**Schema (predict.stock_hunter_performance_stats):**
```
id, user_id, period_type ('all_time'|'ytd'|'30d'|'7d'),
total_recommendations, wins, losses, pending, win_rate, avg_win_percent, avg_loss_percent,
profit_factor, long_win_rate, short_win_rate, high_conf_win_rate, med_conf_win_rate,
low_conf_win_rate, sector_stats (JSONB), best_trade_symbol, best_trade_pnl,
worst_trade_symbol, worst_trade_pnl, calculated_at
```

**Data Aggregation:** Each scan aggregates: Finnhub fundamentals (P/E, P/B, EV/EBITDA, ROE, growth metrics), technicals (RSI, SMA50/200, MACD, ATR, trend), sentiment (news score, analyst consensus, social mentions, human/automation score), patterns (candlestick, FVG, support/resistance), market context (VIX level, regime).

**LLM Constraints:** Cite-or-refuse (every claim must reference provided data), conservative bias (hold when uncertain), risk-first mentality, Zod schema validation on output.

**Schema (trading.price_action_patterns):**
```
id, user_id (null for AI-detected), symbol, asset_class, pattern_type
(cluster_breakout_retest|support_bounce|resistance_rejection|breakout_continuation|
false_breakout|double_bottom|double_top|higher_low|lower_high),
direction (bullish|bearish|neutral), status (forming|triggered|confirmed|failed|completed),
confidence, levels[], cluster_high, cluster_low, triggered_at, confirmed_at, failed_at,
trade_suggestion (entry/stop/target/rr), notes, metadata, detected_at, expires_at,
-- Regime context (migration 181)
regime_at_detection, regime_confidence, regime_adjusted_confidence, regime_multiplier
```

**Schema (trading.pattern_historical_stats):**
```
id, pattern_type, regime (nullable), asset_class (nullable), direction (nullable),
sample_size, hits, misses, hit_rate, hit_rate_ci_lower, hit_rate_ci_upper,
median_move_pct, mean_move_pct, stddev_move_pct, move_ci_lower, move_ci_upper,
max_drawdown_before_target, avg_time_to_target_hours, is_significant, p_value, effect_size,
last_computed_at, patterns_analyzed_through
```

**Schema (trading.pattern_templates):**
```
id, user_id, name, description, source_symbol, source_timeframe, source_start_date, source_end_date,
normalized_series[], series_length, original_high, original_low, price_range_pct,
direction, pattern_type, tags[], max_dtw_distance, min_similarity_pct,
total_matches, confirmed_matches, match_hit_rate, last_scanned_at
```

**Related tables:** `pattern_subscriptions`, `pattern_playbook`, `pattern_annotations`, `pattern_trigger_events`, `pattern_warming`, `pattern_template_matches`, `pattern_scan_queue`, `emergency_kill_events`, `pattern_scheduler_rules`, `pattern_time_windows`, `pattern_schedule_slots`, `pattern_schedule_matches`

**Scheduler:** `pattern-detection` job runs every 5 min for active symbols — calls `detectPatterns()` and publishes alerts for new triggered patterns.

### 4o-3. Pattern Auto-Trading (2026-04-21)

Automatic trade execution when high-confidence patterns trigger. Supports paper and live modes with safety limits.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/trading/auto-trade` | mid | Get user's auto-trade config. Returns filters (patternTypes, minConfidence, directions, symbols, assetClasses), position sizing (type, value, maxUsd), safety limits (maxDailyTrades, maxOpenPositions, cooldownMinutes), executionMode (paper\|live). Shipped 2026-04-21. |
| PUT | `/api/predict/v1/trading/auto-trade` | low | Update auto-trade config. Body: all config fields. Validates MFA + broker for live mode. Shipped 2026-04-21. |
| GET | `/api/predict/v1/trading/auto-trade/log` | mid | Get execution history. Query: `?status=executed&symbol=BTCUSDT&limit=50`. Returns trades with PnL tracking. Shipped 2026-04-21. |
| GET | `/api/predict/v1/trading/auto-trade/stats` | mid | Get auto-trade stats: totalTrades, winRate, totalPnl, todayTrades, byPattern breakdown. Shipped 2026-04-21. |

**Schema (trading.pattern_auto_trade_config):**
```
id, user_id, enabled, pattern_types[], min_confidence, directions[], symbols[], asset_classes[],
position_size_type (fixed_usd|percent_portfolio|risk_based), position_size_value, max_position_usd,
use_pattern_stop_loss, use_pattern_target, stop_loss_override_pct, take_profit_override_pct,
max_daily_trades, max_open_positions, cooldown_minutes, execution_mode (paper|live), broker_id
```

**Schema (trading.pattern_auto_trade_log):**
```
id, user_id, pattern_id, symbol, side, quantity, stop_loss, take_profit, status, error,
entry_price, exit_price, pnl, pnl_percent, config_snapshot, execution_metadata, created_at, closed_at
```

**Flow:** Pattern detection (`analyzeSymbol`) → pattern status becomes 'triggered'/'confirmed' → `processPatternForAutoTrade()` finds matching user configs → safety checks (daily limit, cooldown, open positions) → execute via `executeTrade()` → log + push notification.

### 4o-4. Unified Trades API (2026-04-21)

Unified view of all trades across gap, pattern, signal, and mock trading systems.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/trading/all-trades` | mid | List all trades with filtering. Query: `?type=gap&mode=dry_run&status=open&symbol=BTC&search=&limit=100&offset=0`. Returns unified trade records with counts by mode. |
| GET | `/api/predict/v1/trading/all-trades/performance` | mid | Portfolio performance with timeline. Query: `?period=30d&mode=paper`. Returns summary (totalTrades, winRate, totalPnl), timeline (daily P&L), byTradeType, topSymbols. |

**Schema (trading.all_trades view):**
```
id, user_id, symbol, trade_type (gap|pattern|signal|mock), action, quantity,
entry_price, status, is_dry_run, trade_mode (dry_run|paper|live|mock),
created_at, pnl, pnl_percent
```

### 4o-5. Cost Analysis API (2026-04-21)

Pre-trade cost analysis to ensure expected ROI exceeds trading costs.

| Method | Path | Rate | Notes |
|---|---|---|---|
| POST | `/api/predict/v1/trading/cost-analysis` | mid | Analyze single trade for cost-effectiveness. Body: `{symbol, assetClass, side, quantity, entryPrice, expectedExitPrice, signalConfidence}`. Returns shouldTrade, netPnl, costs, recommendations. |
| POST | `/api/predict/v1/trading/cost-analysis/rank` | mid | Rank multiple opportunities by cost-adjusted quality. Body: `{opportunities: [...]}`. Returns rankings with overall score. |
| GET | `/api/predict/v1/trading/cost-analysis/schedule` | mid | Get cost schedule for asset class. Query: `?assetClass=crypto&orderValue=10000`. Returns fees, slippage estimates. |
| GET | `/api/predict/v1/trading/cost-analysis/min-size` | mid | Calculate minimum profitable position size. Query: `?assetClass=stock&entryPrice=100&expectedMove=2&targetReturn=0.5`. |

**Cost breakdown includes:** Entry fees, exit fees, entry slippage, exit slippage, break-even move required.

### 4o-6. Market Regime API (2026-04-21)

Market regime classification and algorithm weight adjustments.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/trading/regime` | mid | Get current market regime. Returns regime (BULL/BEAR/SIDEWAYS/CRISIS/RECOVERY), confidence, indicators (VIX, fear/greed, trend strength, yield curve), tradingGuidance[], recommendedAlgorithms[], riskMultiplier. |
| GET | `/api/predict/v1/trading/regime/weights` | mid | Get regime-adjusted algorithm weights. Returns baseWeights, adjustedWeights, adjustments by algorithm. |
| GET | `/api/predict/v1/trading/regime/status` | mid | Check if trading should be paused. Returns tradingAllowed, pauseReason, tradingGuidance[]. |
| GET | `/api/predict/v1/trading/regime/history` | mid | Get regime history and transitions. Query: `?days=30&limit=100`. Returns history[], distribution, transitions[]. |
| GET | `/api/predict/v1/trading/regime/performance` | mid | Get algorithm performance by regime. Returns performance metrics per algorithm per regime. |

**Regime indicators:** VIX (current + 5d change), trend strength (-1 to +1), volatility percentile, yield curve slope, fear/greed index, market breadth, correlation spike detection.

### 4o-7. Trading Guardrails API (2026-04-21)

Configurable safety limits and complete audit logging for all trading decisions.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/trading/guardrails` | mid | Get user's guardrail config and defaults. Returns config (position limits, daily limits, kill switches) + defaults. |
| PUT | `/api/predict/v1/trading/guardrails` | low | Update guardrail config. Body: partial config object. |
| POST | `/api/predict/v1/trading/guardrails/check` | mid | Check guardrails for potential trade. Body: `{portfolioId, symbol, assetClass, side, quantity, price, signalConfidence}`. Returns passed, violations[], warnings[]. |
| GET | `/api/predict/v1/trading/guardrails/history` | mid | Get guardrail violation history for audit. Query: `?days=7&limit=100`. Returns history with byRule summary. |
| GET | `/api/predict/v1/trading/guardrails/rules` | mid | Get available guardrail rules documentation. Returns all rules with descriptions and config keys. |
| POST | `/api/predict/v1/trading/guardrails/kill-switch` | low | **Admin only.** Toggle global kill switch. Body: `{enabled: boolean, reason: string}`. |

**Guardrail rules (12+):**
- `GLOBAL_KILL_SWITCH` — Platform-wide trading halt
- `MAX_ORDER_VALUE` — Single order value limit
- `MAX_POSITION_PERCENT` — Position as % of portfolio
- `MAX_OPEN_POSITIONS` — Concurrent positions limit
- `MAX_DAILY_TRADES` — Trades per day limit
- `DAILY_LOSS_LIMIT_USD` — Daily loss cap
- `MIN_CONFIDENCE` — Signal confidence threshold
- `COOLDOWN` — Min time between same-symbol trades
- `ASSET_CLASS_BLOCKED` — Allowed asset classes filter
- `SYMBOL_BLOCKED` — Blocked symbols list
- `INSUFFICIENT_BALANCE` — Balance check

**Full audit logging:** Every check, block, and warning logged to `trading.guardrail_log` with user_id, portfolio_id, symbol, rule, details, result, timestamp.

### 4o-8. Advanced Risk Metrics API (2026-04-23)

Institutional-grade risk metrics including liquidity analysis, tail risk (GPD VaR), drawdown decomposition, and optimal position sizing.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/trading/risk/summary` | mid | Basic risk summary. Returns dailyPnl, drawdown limits, alerts, intraday equity curve. |
| GET | `/api/predict/v1/trading/risk/advanced` | mid | **Advanced metrics.** Returns liquidityRisk (days-to-liquidate, illiquid positions), gpdVaR (Extreme Value Theory), drawdownAnalysis (Ulcer Index, Pain Index, recovery times), returnQuality (Ljung-Box autocorrelation, Newey-West volatility), tailHedge recommendations. |
| POST | `/api/predict/v1/trading/risk/position-size` | mid | **Optimal position sizing.** Body: `{symbol, desiredSize, price, assetVolatility, targetVolContribution, avgDailyVolume}`. Returns recommendation (vol-adjusted, correlation-adjusted, liquidity-constrained sizes), constraints[], liquidityCheck. |

**Advanced metrics breakdown:**

- **Liquidity Risk:** Portfolio-wide liquidity assessment with weighted days-to-liquidate, illiquid position warnings, and overall risk classification (low/medium/high/critical)
- **GPD VaR:** Generalized Pareto Distribution VaR using Extreme Value Theory for tail risk estimation (99% confidence)
- **Drawdown Analysis:** Ulcer Index, Pain Index, average recovery days, max underwater days, worst event details
- **Return Quality:** Ljung-Box autocorrelation test (p-value), raw vs Newey-West adjusted volatility, volatility adjustment factor
- **Tail Hedge:** Automated recommendations (buy_puts, reduce_exposure, add_bonds, increase_cash) with urgency levels and suggested sizes
- **Position Sizing:** Volatility-adjusted (risk parity), correlation-aware (diversification penalty), liquidity-constrained (5-day exit requirement)
- **Time-of-Day Liquidity:** Current liquidity multiplier based on market session (US open/close premium, midday discount, after-hours penalty)

### 4o-9. Tax Lot & LLM Tax Rules API (2026-05-05)

Tax lot tracking, wash sale detection, tax-loss harvesting opportunities, and LLM-powered tax analysis. **All responses include a disclaimer that this is for informational purposes only and does NOT constitute tax advice.**

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET, PUT | `/api/predict/v1/tax/settings` | mid | User tax settings (jurisdiction, rates, lot selection method, TLH alerts). |
| GET | `/api/predict/v1/tax/jurisdictions` | high | Available tax jurisdictions with rates and rules (US, UK, CA, AU, DE, SG). |
| GET | `/api/predict/v1/tax/lots` | mid | List user's tax lots. Query: `?symbol=AAPL&includeClosed=false&limit=50&offset=0`. |
| POST | `/api/predict/v1/tax/lots` | mid | Create tax lot. Body: `{symbol, acquisitionDate, quantity, costBasisUsd, assetClass?, acquisitionType?, commissionUsd?}`. |
| POST | `/api/predict/v1/tax/lots/sell` | mid | Record sale against lots. Body: `{symbol, quantity, proceedsUsd, saleDate?, lotSelectionMethod?, specificLotIds?}`. Returns realized gain/loss breakdown. |
| GET | `/api/predict/v1/tax/summary` | mid | Tax year summary. Query: `?year=2026`. Returns short/long-term gains/losses, wash sale disallowed. |
| GET | `/api/predict/v1/tax/wash-sales` | mid | Active wash sale windows (30-day tracking). |
| GET | `/api/predict/v1/tax/tlh` | mid | Pending tax-loss harvesting opportunities. |
| POST | `/api/predict/v1/tax/tlh` | mid | Get LLM TLH recommendation. Body: `{symbol, currentLoss, costBasis, recentTrades[]}`. Returns action, reasoning, replacements. |
| POST | `/api/predict/v1/tax/analyze` | low | **LLM tax analysis.** Body: `{jurisdiction, scenario, context}`. Scenarios: `wash_sale`, `holding_period`, `crypto_treatment`, `foreign_income`, `gift_inheritance`, `nft_collectibles`. Returns holding period, wash sale check, estimated tax, recommendations. |
| POST | `/api/predict/v1/tax/analyze/substantially-identical` | mid | Check if replacement security is substantially identical. Body: `{originalSymbol, replacementSymbol, jurisdiction?}`. |
| GET | `/api/predict/v1/tax/education` | high | Tax education content. Query: `?jurisdiction=US&topic=wash_sale`. Topics: `wash_sale`, `holding_period`, `crypto`, `loss_harvesting`, `general`. |

**Lot selection methods:** FIFO (first-in-first-out), LIFO (last-in-first-out), HIFO (highest-cost-first), tax_optimal (LLM-assisted).

**⚠️ Disclaimer:** All tax features are for educational/informational purposes only. Users must consult qualified tax professionals (CPA, EA, tax attorney) for actual tax decisions.

### 4o-10. Portfolio Reports & Export API (2026-05-05)

Export portfolio and trading data as PDF or CSV reports.

| Method | Path | Rate | Notes |
|---|---|---|---|
| POST | `/api/predict/v1/portfolio/export` | low | Generate portfolio report. Body: `{format: 'pdf' \| 'csv', includePositions?, includeTrades?, includeTaxLots?, includeMetrics?, dateRange?}`. Returns download URL. |
| GET | `/api/predict/v1/portfolio/export/[exportId]` | mid | Download generated export file. |

### 4p. API keys (per-user Chrome-extension keys)
| Method | Path | Rate |
|---|---|---|
| GET, POST | `/api/predict/v1/api-keys` | mid |
| GET, DELETE | `/api/predict/v1/api-keys/[keyId]` | mid |

### 4q. Misc
| Method | Path | Rate |
|---|---|---|
| GET | `/api/predict/v1/categories` | high |
| GET, PATCH, DELETE | `/api/predict/v1/categories/[id]` | mid |
| GET | `/api/predict/v1/sources` | high |
| GET, PATCH | `/api/predict/v1/sources/[id]` | mid |
| GET | `/api/predict/v1/signals/unmatched` | mid |
| POST | `/api/predict/v1/signals/unmatched/[id]/match\|discard` | low |

### 4r-1. Economic Calendar (bearer — optional auth, public read)

Four routes. Economic calendar events from Finnhub, FXStreet, and FRED. All `GET` endpoints allow optional auth (work for public access). Admin sync endpoint requires `bearer+admin`.

| Method | Path | Auth | Rate | Notes |
|--------|------|------|------|-------|
| GET | `/api/predict/v1/economic-calendar/events` | bearer (optional) | mid | Upcoming events with filters (country, impact, category, currency, source, date range). Default limit 50, max 100. |
| GET | `/api/predict/v1/economic-calendar/releases` | bearer (optional) | mid | Recent releases (last N hours) with surprise data. Default 24h, limit 20. |
| POST | `/api/predict/v1/admin/economic-calendar/sync` | bearer+admin | low | Manual sync trigger. Returns per-source insert/update counts. |

**Query parameters for `/events`:**
- `country` — ISO country code (US, EU, GB, JP, CN, etc.)
- `countries` — Comma-separated country codes
- `impact` — Impact level(s): low, medium, high, critical
- `category` — employment, inflation, gdp, rates, housing, trade, consumer, manufacturing
- `currency` — USD, EUR, GBP, JPY, etc.
- `source` — finnhub, fxstreet, fred
- `startDate`, `endDate` — Date range (YYYY-MM-DD)
- `limit`, `offset` — Pagination

**Query parameters for `/releases`:**
- `hours` — Hours to look back (default 24)
- `country`, `impact`, `currency` — Filters
- `limit` — Max results (default 20, max 50)

**Response shape:**
```json
{
  "events": [
    {
      "id": "uuid",
      "source": "finnhub",
      "eventName": "Nonfarm Payrolls",
      "country": "US",
      "eventDate": "2026-05-08T12:30:00Z",
      "actualValue": 180000,
      "forecastValue": 175000,
      "previousValue": 165000,
      "unit": "K",
      "impact": "high",
      "category": "employment",
      "currency": "USD",
      "isReleased": true,
      "surprisePct": 2.86
    }
  ],
  "pagination": { "total": 150, "limit": 50, "offset": 0, "hasMore": true }
}
```

**Scheduler:** `economic-calendar-sync` job runs every 6 hours, syncs past 7 days to next 30 days.

See `docs/57-economic-calendar-integration.md` for full documentation.

---

### 4r. AI assistant (in-app chat helper — thin-context v1, no RAG)

Five routes. All `bearer+active`; the `stream` endpoint is SSE and must bypass Kong response buffering (`proxy_buffering off` or the `X-Accel-Buffering: no` header the handler already emits). `stream` is the only LLM-calling route in the app that is user-initiated, **per-turn, and streaming** — gateway config should exempt it from the global request-body-buffering plugin and bump the connection idle timeout to ≥120s.

| Method | Path | Rate | Notes |
|---|---|---|---|
| POST | `/api/predict/v1/assistant/stream` | **low** (30 turns/user/hour enforced server-side) | SSE stream. Events: `meta`, `delta`, `final`, `error`, `done`. Max body 2000 chars. No response buffering. |
| GET | `/api/predict/v1/assistant/threads` | mid | List caller's threads, ordered by `updated_at DESC` (cap 50) |
| GET, DELETE | `/api/predict/v1/assistant/threads/[id]` | mid | Owner-scoped fetch + cascade-delete turns |
| POST | `/api/predict/v1/assistant/feedback` | mid | `{turnId, feedback: -1|0|1}` — ownership validated via join |

Rate-limit profile: server-side enforces 30 turns/user/hour (Redis sorted-set sliding window with in-memory fallback). Kong can add a coarser `30/hr` + `5/minute` burst cap per-consumer as defense-in-depth without duplicating the server logic. See `packages/be/src/assistant/guardrails.ts:MAX_TURNS_PER_WINDOW`.

Auth + onboarding: `stream` requires `requireAuth` today. If the product decides the assistant should be available to `pending_*` users (e.g. "what is this approval queue?"), swap to `requireAuth` without `requireActiveUser` — already the case in v1 so pending-subscription users can ask onboarding questions.

---

## 5. Admin (`bearer+admin`)

All of these require `isAdminRole(user.role)` in the backend. Gateway can additionally enforce via JWT claim inspection (Kong `jwt-claims-headers` plugin). Same rate-limit profile for all — admin traffic is low volume.

```
/api/predict/v1/admin/users              (GET, POST)
/api/predict/v1/admin/users/[id]         (GET, PATCH, DELETE)
/api/predict/v1/admin/users/[id]/approve
/api/predict/v1/admin/users/[id]/reject
/api/predict/v1/admin/users/[id]/mfa
/api/predict/v1/admin/users/[id]/mfa-required
/api/predict/v1/admin/users/[id]/reset-password
/api/predict/v1/admin/users/[id]/suspend
/api/predict/v1/admin/users/[id]/unsuspend

/api/predict/v1/admin/trades                           (GET)     # List all platform trades
/api/predict/v1/admin/trades/export/csv                (GET)     # Export all trades as CSV
/api/predict/v1/admin/trades/export/pdf                (GET)     # Export all trades as PDF

/api/predict/v1/admin/brokers                          (GET)
/api/predict/v1/admin/brokers/[brokerId]               (PATCH)

/api/predict/v1/admin/billing                          (GET)
/api/predict/v1/admin/billing/plans                    (GET, POST)
/api/predict/v1/admin/billing/plans/[id]               (GET, PATCH, DELETE)

/api/predict/v1/admin/cognito                          (GET)
/api/predict/v1/admin/cognito/test                     (POST)
/api/predict/v1/admin/aws                              (GET)
/api/predict/v1/admin/cache                            (GET, DELETE)

/api/predict/v1/admin/integrations                     (GET)
/api/predict/v1/admin/integrations/test                (POST)

/api/predict/v1/admin/algorithms/data-status           (GET)
/api/predict/v1/admin/workflows                        (GET)

/api/predict/v1/admin/service-accounts                 (GET, POST)
/api/predict/v1/admin/service-accounts/[id]            (GET, PATCH, DELETE)
/api/predict/v1/admin/service-accounts/[id]/keys       (GET, POST)
/api/predict/v1/admin/service-accounts/[id]/keys/[keyId] (DELETE)

/api/predict/v1/admin/social-follows                   (GET, POST)
/api/predict/v1/admin/social-follows/[id]              (GET, PATCH, DELETE)
/api/predict/v1/admin/social-follows/[id]/credentials  (PATCH) — Update bot token
/api/predict/v1/admin/social-follows/[id]/poll\|toggle
/api/predict/v1/admin/social-follows/[id]/posts        (GET)

/api/predict/v1/admin/news/sources                     (GET, POST)
/api/predict/v1/admin/news/sources/[id]                (GET, PATCH, DELETE)
/api/predict/v1/admin/news/sources/[id]/probe\|run

/api/predict/v1/admin/flow/sources                     (GET, POST)
/api/predict/v1/admin/flow/sources/[id]                (GET, PATCH, DELETE)
/api/predict/v1/admin/flow/sources/[id]/probe

/api/predict/v1/admin/storage                          (GET, POST)  # System storage monitoring
/api/predict/v1/admin/health                           (GET, POST)  # System health dashboard

/api/predict/v1/admin/assistant/analytics              (GET)        # AI assistant usage analytics (super_admin only)

/api/predict/v1/admin/sessions                         (GET)        # List all active sessions (with user info, device, presence)
/api/predict/v1/admin/sessions/stats                   (GET)        # Session statistics (online count, by device type)
/api/predict/v1/admin/sessions/revoke-all              (POST)       # Bulk logout all users. Body: {excludeAdmins?: boolean}
/api/predict/v1/admin/sessions/user/[userId]           (DELETE)     # Revoke all sessions for specific user

/api/predict/v1/admin/maintenance                      (GET, PUT)   # Maintenance mode. PUT body: {enabled, message?, allowAdmins?}

/api/predict/v1/admin/ai-billing/pricing               (GET, POST)  # List/create model pricing
/api/predict/v1/admin/ai-billing/pricing/[model]       (PUT, DELETE) # Update/delete model pricing
/api/predict/v1/admin/ai-billing/packages              (GET, POST)  # List/create credit packages
/api/predict/v1/admin/ai-billing/packages/[id]         (PUT, DELETE) # Update/delete credit packages
/api/predict/v1/admin/ai-billing/settings              (GET, PUT)   # Platform AI billing settings
/api/predict/v1/admin/ai-billing/credits/[userId]/adjust (POST)     # Adjust user credits (super_admin)

/api/predict/v1/admin/stock-hunter/presets             (GET, POST)  # List/create stock hunter presets
/api/predict/v1/admin/stock-hunter/presets/[id]        (GET, PUT, DELETE) # Get/update/delete preset
```

### 5a-1. AI Billing Administration (super_admin) — Shipped 2026-04-30

Pricing and package management for the AI credits system. All endpoints require `super_admin` role.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/admin/ai-billing/pricing` | mid | List all model pricing. Returns `{model, provider, inputTokenCostPer1k, outputTokenCostPer1k, effectiveFrom}[]` |
| POST | `/api/predict/v1/admin/ai-billing/pricing` | low | Create model pricing. Body: `{model, provider, inputTokenCostPer1k, outputTokenCostPer1k}` |
| PUT | `/api/predict/v1/admin/ai-billing/pricing/[model]` | low | Update model pricing |
| DELETE | `/api/predict/v1/admin/ai-billing/pricing/[model]` | low | Delete model pricing |
| GET | `/api/predict/v1/admin/ai-billing/packages` | mid | List credit packages |
| POST | `/api/predict/v1/admin/ai-billing/packages` | low | Create package. Body: `{name, creditsAmount, priceUsd, bonusPercent?, active?}` |
| PUT | `/api/predict/v1/admin/ai-billing/packages/[id]` | low | Update package |
| DELETE | `/api/predict/v1/admin/ai-billing/packages/[id]` | low | Delete package (soft delete if in use) |
| GET | `/api/predict/v1/admin/ai-billing/settings` | mid | Platform AI billing settings (min top-up, max auto-refills, default daily limits) |
| PUT | `/api/predict/v1/admin/ai-billing/settings` | low | Update settings |
| POST | `/api/predict/v1/admin/ai-billing/credits/[userId]/adjust` | low | Manual credit adjustment. Body: `{amount, reason, type: 'add'\|'remove'\|'set'}`. Full audit trail. |
| GET | `/api/predict/v1/admin/ai-billing/stats` | mid | Platform-wide AI billing statistics. Returns `{totalUsers, activeUsersToday, totalCreditsIssuedCents, totalCreditsUsedCents, usageByMode: {subscription, credits, byok}, usageByModel: {model, calls, tokens, costCents}[], recentTransactions[]}` |

**Design notes:**
- Pricing is **not hardcoded** — super_admin sets per-model costs via the admin UI
- Packages support bonus percentages (e.g., $50 → 5500 credits at 10% bonus)
- Settings include platform-wide defaults (min $5 top-up, max 3 auto-refills before re-auth)
- Adjustments are fully audited with admin ID, reason, and timestamp

### 5a-2. Stock Hunter Preset Administration — Shipped 2026-05-08

Admin management of AI Stock Hunter presets. 39 presets across 18 categories. UI at `/admin/stock-hunter`.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/admin/stock-hunter/presets` | mid | List all presets (including inactive) with admin details. Returns `{presets[], categories[], totalPresets, activePresets}` |
| POST | `/api/predict/v1/admin/stock-hunter/presets` | low | Create preset. Body: `{name, displayName, description?, symbols[], category, sortOrder?}`. Name must be lowercase with underscores only. |
| GET | `/api/predict/v1/admin/stock-hunter/presets/[id]` | mid | Get single preset details |
| PUT | `/api/predict/v1/admin/stock-hunter/presets/[id]` | low | Update preset. Body: `{displayName?, description?, symbols?, category?, sortOrder?, isActive?}` |
| DELETE | `/api/predict/v1/admin/stock-hunter/presets/[id]` | low | Delete preset permanently |

**Built-in categories (18 total):**
- **Healthcare**: pharma_giants, biotech_leaders, medical_devices, healthcare_services
- **Technology**: tech_leaders, semiconductors, software_saas, cybersecurity, cloud_infrastructure, ai_leaders
- **Financials**: megabanks, fintech_payments, asset_managers, insurance
- **Energy**: oil_gas_majors, clean_energy
- **Industrials**: industrial_giants, defense_aerospace, logistics_transport
- **Consumer**: retail_giants, consumer_brands, luxury_apparel
- **Communications**: telecom, media_entertainment
- **Thematic**: ev_ecosystem, metaverse_gaming, space_economy, cannabis, water_resources
- **International**: china_adrs, europe_adrs
- **Other**: reits, materials_mining, etf_majors, crypto_majors, dividend_kings, growth_stocks, value_picks, sp500_movers

**Design notes:**
- Presets are **admin-configurable** — not hardcoded, can be updated without deploys
- Each preset has a unique slug (`name`), display name, description, and symbol list (max 50)
- `isActive` toggle hides presets from users without deleting
- `sortOrder` controls display order within category
- `createdBy` tracks which admin created each preset

### 5a-3. Support Chat with RAG — Shipped 2026-05-08

Internal knowledge-base chat for super_admin and support role users, powered by Claude with RAG on uploaded documentation. See `docs/60-support-chat-rag.md` for full architecture.

**Chat Endpoints (super_admin, support roles):**

| Method | Path | Rate | Notes |
|---|---|---|---|
| POST | `/api/predict/v1/support-chat/stream` | mid | SSE streaming chat with RAG context injection. Body: `{threadId?, message}`. Returns events: meta, delta, final, done |
| GET | `/api/predict/v1/support-chat/conversations` | mid | List user's conversations. Query: `?limit=50`. Returns `{conversations[]}` sorted by saved first, then date |
| GET | `/api/predict/v1/support-chat/conversations/[id]` | mid | Get conversation with all turns. Returns `{conversation, turns[]}` |
| POST | `/api/predict/v1/support-chat/conversations/[id]/save` | low | Toggle bookmark. Body: `{isSaved: boolean}`. Persisted across devices |
| POST | `/api/predict/v1/support-chat/feedback` | low | Rate response. Body: `{turnId, feedback: -1\|0\|1}` |

**Document Management (super_admin only):**

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/admin/support-docs` | mid | List all documents + stats. Returns `{documents[], stats}` |
| POST | `/api/predict/v1/admin/support-docs` | low | Upload document (multipart form). Accepts .md, .txt, .pdf (max 10MB). Auto-chunks and embeds |
| GET | `/api/predict/v1/admin/support-docs/[id]` | mid | Get document details |
| DELETE | `/api/predict/v1/admin/support-docs/[id]` | low | Delete document + chunks from DB and S3 |
| POST | `/api/predict/v1/admin/support-docs/[id]` | low | Reprocess document (re-chunk and re-embed) |
| POST | `/api/predict/v1/admin/support-docs/bulk-ingest` | low | Bulk ingest all .md files from S3 prefix. Body: `{prefix?: string}`. Returns ingestion summary |

**Schema (Migration 196):**
- `predict.support_documents` — Document catalog (filename, status, chunk_count, checksum)
- `predict.support_document_chunks` — Chunks with pgvector embeddings (1536 dims, HNSW index)
- `predict.support_conversations` — Chat threads with `is_saved` bookmark flag
- `predict.support_turns` — Messages with source citations and feedback

**RAG Pipeline:**
1. Documents uploaded to S3 bucket `predict-support-docs`
2. Text extracted (pdf-parse for PDFs)
3. Chunked into ~512-token overlapping segments
4. Embedded via Voyage AI (voyage-3-lite) or OpenAI fallback
5. Stored in pgvector for HNSW similarity search
6. At query time: embed query → find top-5 chunks → inject into Claude prompt → stream response with citations

**UI:**
- `/admin/support-chat` — Chat interface with conversation sidebar, bookmarks, source citations
- `/admin/support-docs` — Document management with drag-drop upload, status indicators

### 5a-4. Platform AI Usage Dashboard — Shipped 2026-05-17

Monitor platform AI key usage by purpose, model, and user. Complements `/admin/llm-usage` (per-user LLM tracking) with platform-level AI infrastructure metrics. UI at `/admin/ai-usage`.

| Method | Path | Rate | Notes |
|---|---|---|---|
| GET | `/api/predict/v1/admin/ai-usage/summary` | mid | Today/7-day/30-day summary. Returns `{today, last7Days, last30Days}` with tokens, cost, requests, errors, unique users |
| GET | `/api/predict/v1/admin/ai-usage/daily` | mid | Daily breakdown by provider/purpose. Query: `?days=30&provider=&purpose=`. Returns `{data[], days}` |
| GET | `/api/predict/v1/admin/ai-usage/by-purpose` | mid | Usage by purpose (RAG, chat, stock-hunter, etc.). Query: `?days=30`. Returns `{data[], days}` with error rates |
| GET | `/api/predict/v1/admin/ai-usage/top-users` | mid | Top consumers. Query: `?days=30&limit=20`. Returns `{data[], days, limit}` |
| GET | `/api/predict/v1/admin/ai-usage/trends` | mid | Daily trends for charts. Query: `?days=30`. Returns `{data[], days}` |
| GET | `/api/predict/v1/admin/ai-usage/by-model` | mid | Usage by AI model. Query: `?days=30`. Returns `{data[], days}` with avg cost per request |

**Schema (Migration 199 — `platform_ai_keys`):**
- `predict.platform_ai_keys` — Platform API keys with purpose flags (rag, chat, stock-hunter, etc.)
- `predict.platform_ai_usage` — Per-request usage tracking (tokens_in, tokens_out, cost_usd, errors)
- `predict.platform_ai_usage_daily` — Daily aggregated metrics for dashboards

**Key Differences from `/admin/llm-usage`:**
| Feature | `/admin/llm-usage` | `/admin/ai-usage` |
|---------|-------------------|-------------------|
| Data source | `predict.ai_usage_log` (per-call) | `predict.platform_ai_usage` (platform keys) |
| Focus | User/org attribution | Purpose/endpoint breakdown |
| Billing | Includes BYOK usage | Platform keys only |
| UI | Overview, Users, Orgs tabs | Overview, Purpose, Models, Users tabs |

**UI:**
- `/admin/ai-usage` — 4-tab dashboard (Overview, By Purpose, By Model, Top Users)
- Links to `/admin/llm-usage` for user-level tracking
- Links to `/admin/platform-ai-keys` for key management
- Links to `/admin/stock-hunter-config` for Stock Hunter cost controls

### 5a. System Administration

The `/admin/storage` endpoint provides comprehensive monitoring of database and object storage:

| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/predict/v1/admin/storage` | Get storage overview (database stats, table sizes, S3 buckets) |
| POST | `/api/predict/v1/admin/storage` | Run maintenance (vacuum, analyze) |

**GET Response Fields:**
- `database.stats` — Database name, size, connections, uptime
- `database.schemas[]` — Per-schema stats (table count, row count, size)
- `database.tables[]` — Per-table stats (rows, size, index size, last vacuum)
- `database.topTablesBySize[]` — Top 10 tables by storage
- `database.topTablesByRows[]` — Top 10 tables by row count
- `s3.connected` — Whether S3/MinIO is accessible
- `s3.buckets[]` — Per-bucket stats (object count, size, last modified)
- `s3.totalSizeBytes` — Total object storage usage

**POST Body (Maintenance):**
```json
{
  "action": "vacuum" | "analyze" | "vacuum_analyze",
  "schema": "predict",  // optional - specific schema
  "table": "events"     // optional - specific table
}
```

---

## 6. Public API-key paths (Chrome extension + external consumers)

Authenticated by `X-API-Key` header; backing user identified by the key's owner.

| Method | Path | Auth | Rate |
|---|---|---|---|
| GET | `/api/public/v1/marketing` | api-key | mid |
| GET | `/api/public/v1/overlays` | api-key | mid |
| GET | `/api/public/v1/predictions` | api-key | mid |
| GET | `/api/public/v1/terminal/snapshot` | api-key | high |

---

## 7. SSE streams (long-lived)

Kong / ALB / CloudFront need **idle timeout ≥ 3600s** + **chunked transfer encoding + buffering OFF** + **no response compression** on these routes. `docker/nginx/nginx.conf` already has this for dev.

| Method | Path | Auth |
|---|---|---|
| GET | `/api/predict/v1/realtime` | bearer |
| GET | `/api/predict/v1/realtime/ai-engine` | bearer |
| GET | `/api/predict/v1/realtime/polymarket` | bearer |
| GET | `/api/predict/v1/realtime/surveillance` | bearer |
| GET | `/api/predict/v1/realtime/stats` | bearer |
| GET | `/api/predict/v1/stream` | bearer |
| GET | `/api/predict/v1/all-seeing-eye/stream/black-swan` | bearer |
| GET | `/api/predict/v1/all-seeing-eye/stream/insights` | bearer |
| POST | `/api/predict/v1/assistant/stream` | bearer | SSE but short-lived (single chat turn, ≤60s typical). Idle timeout ≥120s is enough; no need to match the 3600s realtime profile. Still requires `proxy_buffering off` and no response compression. |

---

## 8. Suggested Kong configuration

Service groups (each maps to one Kong `Service`, routes become Kong `Routes`):

| Kong Service | Upstream | Paths | Plugins |
|---|---|---|---|
| `agencio-public` | web | `/api/health`, `/api/predict/v1/auth/*`, `/api/predict/v1/billing/webhooks/stripe` | `cors`, `rate-limiting` (low bucket on auth routes, burst on webhooks) |
| `agencio-bearer` | web | `/api/predict/v1/*` except admin and streams | `jwt`, `rate-limiting` (mid), `request-transformer` (strip internal headers) |
| `agencio-admin` | web | `/api/predict/v1/admin/*` + admin-gated endpoints | `jwt`, `jwt-claims-headers` (extract role), `acl` (admin only), `rate-limiting` (low) |
| `agencio-stream` | web | `/api/predict/v1/realtime/*`, `/api/predict/v1/stream`, `/api/predict/v1/all-seeing-eye/stream/*` | `jwt`, `rate-limiting` (low concurrent-connections), `response-transformer` (no gzip), override `proxy_read_timeout` to 3600s |
| `agencio-assistant` | web | `/api/predict/v1/assistant/stream` | `jwt`, `rate-limiting` (30/hr per-consumer as defense-in-depth — server-side is authoritative), `response-transformer` (no gzip), override `proxy_read_timeout` to 120s. Non-stream assistant routes (`/threads*`, `/feedback`) ride on `agencio-bearer`. |
| `agencio-api-key` | web | `/api/public/v1/*` | `key-auth`, `rate-limiting` (tight per-key quota) |

Rate-limit buckets (per-minute; adjust per tier):
- **burst**: 600/min — health + Stripe webhook
- **high**: 300/min — read-heavy endpoints (market data, sentiment, feeds)
- **mid**: 60/min — standard CRUD
- **low**: 20/min — mutations, LLM calls, backtests, admin writes

JWT config for Kong:
- `key_claim_name: iss` (set to whoever signs — either local or Cognito)
- `claims_to_verify: exp`
- `header_names: Authorization`
- `uri_param_names: jwt` (disable if not needed)
- For Cognito-issued tokens, load the Cognito JWKS key into Kong via the `jwt` plugin's `rsa_public_key` field per key id, or use `jwt-signer` plugin for JWKS discovery.

---

## 9. What a gateway does **not** replace

The backend handlers do their own:
- **Auth** — `requireAuth` / `requireActiveUser` / `isAdminRole` — gateway cuts the volume but the backend is the source of truth
- **Onboarding routing** — 403 `ONBOARDING_REQUIRED` with `details.nextStep` in the error body; frontend `apiFetch` handles this
- **Per-user scoping** — every SQL write has `WHERE user_id = $x`; gateway can't enforce row-level isolation
- **Stripe webhook signature** — must reach the backend with the raw body intact; Kong must NOT transform the body on that route
- **Rate-limiting enforcement for admin kill actions** (PANIC, suspend) — these should bypass gateway rate-limit as they're admin-only and low-volume

---

## 10. Summary

**450 route files** across:
- 2 public (health + Stripe webhook)
- 14 auth / onboarding (public → bearer mid-flow)
- ~321 user-scoped bearer (active required on high-stakes mutations)
- 41 admin (bearer + admin-role)
- 4 API-key public
- 8 SSE streams (long-lived)
- 10 scheduler / internal (admin)

**Added 2026-04-20:**
- Account deletion: `DELETE /user/account`
- Avatar upload: `POST /user/avatar/presigned`, `PUT /user/avatar`, `DELETE /user/avatar`
- Trades: `GET /trades`, `GET /trades/[id]`
- **Algorithm Enhancements (14 routes):**
  - Live metrics: `GET/POST /algorithms/[id]/live-metrics`, `GET /algorithms/live-dashboard`
  - Risk controls: `GET/PUT/POST /algorithms/[id]/risk-controls`
  - AI suggestions: `GET/POST /algorithms/[id]/ai-suggestions`, `POST/DELETE/PATCH /algorithms/ai-suggestions/[suggestionId]`
  - Walk-forward: `POST /algorithms/[id]/walk-forward`
  - Monte Carlo: `POST /algorithms/[id]/monte-carlo`
  - Templates: `GET /algorithms/templates`, `GET/POST /algorithms/templates/[templateId]`
  - Leaderboard: `GET /algorithms/leaderboard`, `GET /algorithms/leaderboard/my-rankings`, `POST/DELETE /algorithms/[id]/leaderboard`
  - Graduation: `GET/POST/PUT /algorithms/[id]/graduation`, `POST /algorithms/[id]/graduation/acknowledge`

**Added 2026-04-21:**
- **Price-Action Patterns (13 routes):**
  - Pattern CRUD: `GET/POST /patterns`, `GET/PUT/DELETE /patterns/[id]`
  - Detection: `POST /patterns/detect`, `GET /patterns/active`
  - Subscriptions: `GET/POST /patterns/subscriptions`, `DELETE /patterns/subscriptions/[id]`
  - Playbook: `GET/POST /patterns/playbook`, `POST /patterns/playbook/[id]/fork`

**Added 2026-04-26:**
- **Trade Compliance & Admin Trades (5 routes):**
  - User exports: `GET /export/trades/csv` (Pro+), `GET /export/trades/pdf` (Enterprise)
  - Admin trades: `GET /admin/trades`, `GET /admin/trades/export/csv`, `GET /admin/trades/export/pdf`
  - Tier gating: CSV requires Pro+, PDF requires Enterprise, history limits enforced by tier

**Added 2026-04-28:**
- **Imported Datasets — backdated S3 history for backtests (7 routes):**

  Lets users (and admins) import OHLCV history from S3 into `predict.market_price_history` so backtests can run against curated data instead of the live provider chain. Two scopes — `user` (private, owner-only) and `system` (admin-curated, tier-gated, per-user subscription). Bars are tagged `source='import:<datasetId>'`.

  | Method | Path | Auth | Notes |
  |---|---|---|---|
  | GET | `/api/predict/v1/datasets` | bearer | Lists own + subscribed + available system datasets. Each row carries `subscribed`/`owned` flags. |
  | POST | `/api/predict/v1/datasets` | bearer | Imports a CSV from S3 to `scope='user'`. Body: `{s3Bucket, s3Key, symbol, assetClass, timeframe?, format?, name?, description?}`. Imports run inline; returns `{dataset, result}` with `rowsImported`/`sha256`/`dateRange*`. |
  | GET | `/api/predict/v1/datasets/[id]` | bearer | Catalog row. Forbidden when scope=user and caller is not owner. |
  | GET | `/api/predict/v1/datasets/[id]/preview` | bearer | First 50 bars, gated by `canAccessDataset`. |
  | POST | `/api/predict/v1/datasets/[id]/subscribe` | bearer | Opt-in to a `scope='system'` dataset. Throws 402 (`PAYMENT_REQUIRED`) when `tier_required` doesn't match the user's active plan. |
  | DELETE | `/api/predict/v1/datasets/[id]/subscribe` | bearer | Unsubscribe (no tier check). |
  | GET | `/api/predict/v1/admin/datasets` | bearer+admin | Lists all datasets across both scopes. |
  | POST | `/api/predict/v1/admin/datasets` | bearer+admin | Imports a CSV to `scope='system'`. Body adds `tierRequired` (matches `billing.subscription_plans.name`; `null` = available to all tiers). |
  | DELETE | `/api/predict/v1/admin/datasets/[id]` | bearer+admin | Removes catalog row + cascades subscriptions. Bars stay in `market_price_history`. |
  | POST | `/api/predict/v1/admin/datasets/[id]/reimport` | bearer+admin | Re-runs the importer (sha256 short-circuits if file unchanged). |

  CSV parser is tolerant: header lookup is case-insensitive and accepts `timestamp`/`time`/`date`/`datetime`, `open`/`o`, `high`/`h`, `low`/`l`, `close`/`c`/`adj_close`, `volume`/`vol`/`v`. Open/high/low default to `close` when absent (close-only feeds). Timestamps accept ISO-8601 or unix ms/seconds.

  **Backtest integration**: every backtest entry point accepts `datasetId` so user-built and AI-created algorithms can both run against imported data:
  | Endpoint | How to pass `datasetId` |
  |---|---|
  | `POST /algorithms/[id]/backtest` | Query `?datasetId=...` or POST body `{datasetId}`. Symbol/asset class are taken from the dataset. |
  | `POST /algorithms/[id]/walk-forward` | POST body `{datasetId}`. All IS+OOS sub-backtests use the dataset. |
  | `POST /algorithms/[id]/monte-carlo` | POST body `{datasetId}`. Seed backtest uses the dataset; resampling is dataset-agnostic. |
  | `POST /algorithms/[id]/stress-test` | POST body `{datasetId}`. Note: a regime window will return `ok=false` when its date range falls outside the dataset's `date_range`. |
  | `POST /algorithms/[id]/modifications/generate` | POST body `{datasetId}`. The LLM-Jury Defense-4 cross-validation backtest uses the dataset, so AI-proposed parameter changes are validated against the same curated history. |

  Access is gated through `canAccessDataset(userId, datasetId)` — owner for user-scope, subscriber for system-scope. Tier enforcement happens at subscribe time; downgraded users keep historical access until they explicitly unsubscribe.

  Storage bucket: `predict-datasets` (added to `BUCKETS` registry in `packages/be/src/lib/storage/index.ts`). Underlying object key is whatever the user provides — typically `users/<userId>/<symbol>-<timeframe>.csv` or `system/<symbol>-<vendor>-<years>.csv`.

  Migration: `db/migrations/135_imported_datasets.sql`.

- **Shared Backtest Service (`apps/backtest-service`) — sibling app, separate auth domain:**

  Standalone Next.js service (port 4400) that stores curated bars
  independently from Predict. Multi-tenant: each consuming app holds an
  API key scoped to a tenant, datasets are owned by a tenant, and
  visibility is `private` / `shared` / `public`. Predict consumes via the
  remote-client when `BACKTEST_SERVICE_URL` + `BACKTEST_SERVICE_API_KEY`
  are set; otherwise Predict stays local-only.

  | Method | Path | Auth | Notes |
  |---|---|---|---|
  | GET | `/api/v1/health` | public | DB ping |
  | GET | `/api/v1/datasets` | `X-API-Key` (read) | Own + shared + public datasets |
  | POST | `/api/v1/datasets` | `X-API-Key` (write) | Import from S3, body includes `visibility` |
  | GET | `/api/v1/datasets/[id]` | `X-API-Key` (read) | Catalog row (owner OR public OR subscribed) |
  | DELETE | `/api/v1/datasets/[id]` | `X-API-Key` (write) | Owner only |
  | GET | `/api/v1/datasets/[id]/bars?from=&to=&limit=` | `X-API-Key` (read) | Up to 200k bars |
  | GET | `/api/v1/datasets/[id]/preview` | `X-API-Key` (read) | First 50 bars |
  | POST/DELETE | `/api/v1/datasets/[id]/subscribe` | `X-API-Key` (write) | Tenant subscribes/unsubscribes (shared only) |
  | POST | `/api/admin/tenants` | `X-Admin-Token` | Bootstrap a tenant + initial API key (raw key returned ONCE) |
  | POST | `/api/admin/api-keys` | `X-Admin-Token` | Mint additional keys |

  **Predict integration**: `predict.imported_datasets.storage_target =
  'remote'` rows are imported via the service and read back via the
  remote client. The backtest engine, walk-forward, monte-carlo, regime
  stress, and AI-modifications cross-validation are all storage-target
  agnostic — they call `loadImportedBars` which routes by `storage_target`.

  Migrations: `db/migrations/136_backtest_service.sql` (`bks.*` schema),
  `db/migrations/137_dataset_storage_target.sql` (Predict catalog
  routing column). Deployment: see TODO.md → "Shared backtest service —
  AWS deployment".

**Added 2026-04-30:**
- **AI Billing Credits System (23 routes):**
  - User Settings UI: `/settings/ai-billing`, `/settings/ai-billing/credits`, `/settings/ai-billing/byok`, `/settings/ai-billing/usage`
  - Admin UI: `/admin/ai-billing` (Overview, Packages, Pricing tabs with super_admin gating)
  - AI Billing Config: `GET/PUT /ai-billing`, `GET /ai-billing/usage`, `GET /ai-billing/credits/packages`, `POST /ai-billing/credits/checkout`, `GET /ai-billing/credits/transactions`, `PUT /ai-billing/credits/auto-refill`, `GET/POST /ai-billing/byok`, `DELETE /ai-billing/byok/[id]`, `POST /ai-billing/byok/[id]/validate`
  - Org Limits: `GET/PUT /org/ai-limits`, `GET /org/ai-limits/usage`, `GET/PUT /org/ai-limits/member/[userId]`
  - Admin: `GET/POST /admin/ai-billing/pricing`, `PUT/DELETE /admin/ai-billing/pricing/[model]`, `GET/POST /admin/ai-billing/packages`, `PUT/DELETE /admin/ai-billing/packages/[id]`, `GET/PUT /admin/ai-billing/settings`, `POST /admin/ai-billing/credits/[userId]/adjust`, `GET /admin/ai-billing/stats`
  - Three billing modes: subscription (included with tier), credits (pay-per-use), BYOK (bring your own key)
  - Credit reservation system prevents overdraft during in-flight LLM calls
  - AES-256-GCM encryption for BYOK keys with per-user derived keys
  - Org-level spending caps with per-member daily tracking

**Added 2026-05-07:**
- **Pattern Scheduler (16 routes):**
  - Rules CRUD: `GET/POST /patterns/scheduler/rules`, `GET/PUT/DELETE /patterns/scheduler/rules/[id]`
  - Rule actions: `POST /patterns/scheduler/rules/[id]/toggle`, `POST /patterns/scheduler/rules/[id]/test`
  - Time windows: `POST /patterns/scheduler/time-windows`, `PUT/DELETE /patterns/scheduler/time-windows/[id]`
  - Schedule slots: `POST /patterns/scheduler/slots`, `PUT/DELETE /patterns/scheduler/slots/[id]`
  - Reference data: `GET /patterns/scheduler/presets`, `GET /patterns/scheduler/timezones`, `GET /patterns/scheduler/pattern-types`, `GET /patterns/scheduler/markets`
  - Complex pattern rules with AND/OR/NOT/THEN/XOR logic operators
  - Timezone-aware time windows with active/blackout hours
  - Multi-market support with AI auto-detection
  - Market session presets (NYSE, NASDAQ, LSE, forex 24/5, crypto 24/7, etc.)
  - Visual drag-drop timeline (desktop-only) with mobile warning
  - Migration: `db/migrations/188_pattern_scheduler.sql`

Fronting with Kong gives you: centralized rate-limits, JWT verification one layer up, TLS termination outside the app, per-consumer quotas on API keys, and a dashboard for traffic by route. The backend remains the authoritative source of auth + onboarding decisions. See § 8 for a starting Kong service-and-route config.
