Skip to content

API Reference

All routes are under /api. The global rate limit is 200 requests/min per IP (Fiber in-memory token bucket). Per-endpoint overrides are noted below.

ENV=production disables the dev-only routes. The ComingSoonGate middleware returns 503 to non-admin users on all protected routes when the coming_soon feature flag is true.

Auth (public)

Method Path Auth Rate limit Purpose
POST /api/auth/google None 20/min Verify Google idToken + nonce. Returns 200 (existing user + cookies) or 422 (new user + reg ticket + OTP sent).
POST /api/auth/google/complete None 10/min Complete registration with reg ticket + profile fields. Creates user row, sets cookies.
POST /api/auth/verify-otp None 10/min Verify 6-digit OTP from email. Sets regotp:verified:<sub> in Redis.
POST /api/auth/resend-otp None 5/min Re-send OTP email. Subject to 60s cooldown; returns 429 with Retry-After header if active.
POST /api/auth/refresh Refresh cookie Global Rotate refresh token, issue new access+refresh pair.
POST /api/auth/logout Optional Global Revoke access + refresh JTIs, clear cookies. Idempotent.
POST /api/users/check-username None 60/min Check whether a username is available and valid.
GET /api/flags None Global Public feature flag map (boolean values; admin toggle is privileged).
GET /api/public/referral/validate None 10/min Validate a referral code. Always 200; valid:false for unknown codes.
GET /api/me Optional (JWT) Global Returns {loggedIn:false} when unauthenticated, full profile when authenticated.

Dev-only (disabled when ENV=production):

Method Path Auth Purpose
POST /api/auth/dev None Create/login synthetic user by display name (idempotent).
POST /api/auth/dev/batch None Batch-create up to 1000 synthetic users for load testing.

WebSocket token

Method Path Auth Purpose
POST /api/ws/token JWT Issue a 60-second ws-token for WebSocket upgrade.

Instruments

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/instruments | JWT | All active instruments. | | GET | /api/instruments/movers | JWT | Top 5 gainers, losers, most-traded (24h window, 60s Redis cache). | | GET | /api/instruments/:id | JWT | Single instrument by UUID. | | GET | /api/instruments/:id/price-history | JWT | Price ticks. Query params: period (5m, 1h, 6h, 1d, all). Max 500 ticks. | | GET | /api/instruments/:id/recent-trades | JWT | Most recent trades for an instrument (excludes user IDs). |

Matches

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/matches | JWT | All fixtures. | | GET | /api/matches/:id/events | JWT | In-game events from Redis events:{sportmonksId} list. | | GET | /api/matches/:id/squad | JWT | Squad for home or away team (?team=home\|away). |

CFD Positions

Current trading model (ADR-0004). Use these endpoints for new integrations.

| Method | Path | Auth | Purpose | |---|---|---| | POST | /api/positions/open | JWT | Open a long or short CFD position. Pass Idempotency-Key header. | | GET | /api/positions | JWT | List the caller's open positions. | | PATCH | /api/positions/:id | JWT | Modify SL/TP on an open position. | | POST | /api/positions/:id/close | JWT | Close a position. Pass Idempotency-Key header. |

Note

CFD endpoints are only registered when positions.Service is wired (always the case in api-server). The 180s per-instrument cooldown now gates closes, not opens.

Legacy Trades

Buy-and-hold model (pre-ADR-0004). Kept live during rollout; clients using these still work.

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/trades | JWT | Caller's trade history (limit, offset query params). |

Note

The legacy POST /api/trade endpoint (direct BUY/SELL) is not present in handler.Register. Trade execution for legacy shares goes through the sportmonks post-match auto-seller (trade.ExecuteSystemSell) at FT.

Portfolio & Wallet

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/portfolio | JWT | Open positions (legacy shares), wallet balance, total PnL. | | GET | /api/wallet | JWT | Wallet balance. |

Leaderboard

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/leaderboard/global | JWT | Global PnL leaderboard (limit up to 500). | | GET | /api/leaderboard/district/:districtId | JWT | District PnL leaderboard. | | GET | /api/leaderboard/roi/global | JWT | Global ROI leaderboard (primary scoring for launch). | | GET | /api/leaderboard/roi/district/:districtId | JWT | District ROI leaderboard. | | GET | /api/leaderboard/roi/friends | JWT | Referral-network ROI leaderboard. | | GET | /api/leaderboard/friends | JWT | Referral-network PnL leaderboard (legacy). | | GET | /api/leaderboard/me | JWT | Caller's rank entry. Returns {ranked:false} before first trade. | | GET | /api/leaderboard/me/context | JWT | Caller's rank + gap to next rank (for goal-gradient UI). | | GET | /api/districts/standings | JWT | Cross-district aggregate standings. |

Spinner

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/spinner/current | JWT | Current week's winner or tied candidates. | | GET | /api/spinner/history | JWT | Recent weekly winners (limit default 12). | | POST | /api/spinner/run | JWT | Trigger the spin. Idempotent. |

Notifications

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/notifications | JWT | List notifications (limit, unreadOnly=true). | | GET | /api/notifications/unread-count | JWT | Count of unread notifications. | | POST | /api/notifications/:id/read | JWT | Mark one notification read. | | POST | /api/notifications/read-all | JWT | Mark all notifications read. |

Activity

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/activity | JWT | Social-proof feed. scope=global\|district, districtId, limit. |

Referrals

Method Path Auth Rate limit Purpose
POST /api/referral/validate JWT 30/min Validate a referral code (protected; requires JWT).
POST /api/referrals/invites JWT 30/min Create a named per-invite share link.
GET /api/referrals JWT Global List the caller's referrals (named invites + anonymous).

Achievements

| Method | Path | Auth | Purpose | |---|---|---| | GET | /api/achievements | JWT | Caller's earned + locked badges. |

Admin

All admin routes require role=admin in the JWT (AdminOnly middleware).

Method Path Purpose
GET /api/admin/flags List all feature flags.
PUT /api/admin/flags/:key Set a feature flag value.
GET /api/admin/settings List all admin settings.
PUT /api/admin/settings/:key Set an admin setting (triggers OnUpdate callbacks live).
GET /api/admin/settings/scoring/multiplier-keys List scoring position multiplier keys.
GET /api/admin/users List all users.
GET /api/admin/users/export.csv Export all users as CSV.
GET /api/admin/gameplay-bot/fixtures List bundled replay fixtures.
GET /api/admin/gameplay-bot/status Current replay state.
POST /api/admin/gameplay-bot/start Start a fixture replay.
POST /api/admin/gameplay-bot/stop Stop a running replay.