API v1 coverage audit · 2026-05-19
Scope
Audit + enrichment of the public REST API surface under /api/v1/*.
Goal: smart query filters, score breakdown coverage, insider history, leaderboards.
Endpoint inventory
Before (28 routes)
| Path | Auth | Purpose |
|---|---|---|
/api/v1/me |
key | Identity + key |
/api/v1/health |
public | DB health + freshness |
/api/v1/stats/summary |
public | Surface counters |
/api/v1/stats |
key | Rich counters |
/api/v1/markets |
key | Catalogue |
/api/v1/companies |
key | Issuer list |
/api/v1/companies/{slug} |
key | Issuer detail |
/api/v1/companies/{slug}/declarations |
key | Per-issuer trades |
/api/v1/companies/{slug}/insider-flow |
key | Net buy/sell flow |
/api/v1/insiders |
key | Insider list |
/api/v1/insiders/{slug} |
key | Insider detail |
/api/v1/insiders/{slug}/declarations |
key | Per-insider trades |
/api/v1/insiders/{slug}/timeline |
key | Chronological timeline |
/api/v1/declarations |
key | Full declarations search |
/api/v1/declarations/{amfId} |
key | Single declaration + backtest |
/api/v1/signals |
key | Top scored signals |
/api/v1/clusters |
key | Multi-insider clusters |
/api/v1/scoring/explain/{amfId} |
key | 9-factor score breakdown |
/api/v1/backtest |
key | Aggregated returns + win rate |
/api/v1/oos-performance |
public | OOS realized returns |
/api/v1/strategy/winning |
key | Sigma Winning Strategy cohort |
/api/v1/search |
key | Cross-entity fuzzy search |
/api/v1/export |
key (tier-gated) | Bulk Parquet / CSV |
/api/v1/sandbox/{path} |
anon (10/24h) | Anonymous proxy |
/api/v1/sandbox/challenge |
public | POW challenge |
/api/v1/sandbox/status |
public | Quota check |
/api/v1/admin/seed |
admin | Seed sample data |
/api/v1/internal/dump |
internal | Ops dump |
After (33 routes · 5 new)
New endpoints added:
/api/v1/recommendations(key, tier-aware) Mode-driven top picks.mode=general|sells|personal, lookback window, market/role/mcap/cluster filters. PRO+ get backtest summary per pick./api/v1/leaderboard/insiders(key) Top insiders bytotalAmount,tradeCount,avgScore,maxScoreoverperiod=ytd|30d|90d|180d|365d|all. Role + market filters, minTrades floor./api/v1/leaderboard/companies(key) Top issuers bynetBuy,netSell,tradeCount,distinctInsiders,avgScore,totalAmount. Market + mcap band filters./api/v1/sectors(key) Aggregated insider flow per sector tag (FR or EN label), per-period. Powers sector-rotation screens./api/v1/score/distribution(key) Score histogram (configurable bucket size) + mean / min / max / p10/p25/p50/p75/p90/p95/p99 percentiles over a cohort.
Smart filter enrichment (existing endpoints)
| Endpoint | New params |
|---|---|
/declarations |
role (CSV), maxAmount (was missing) |
/signals |
from, to, market, role, minAmount, minMcap, maxMcap, cluster, sort, order, offset |
/clusters |
minScore, market, sort=latest|distinctInsiders|avgScore|totalAmount |
/insiders |
role (CSV), minDeclarations, sort=name|declarations, order |
/insiders/{slug}/declarations |
from, to, direction, companies (CSV slug/yahoo), minScore, minAmount, sort, order |
/companies/{slug}/declarations |
from, to, minAmount, cluster, sort, order |
All filters share a single source of truth: src/lib/api-filters.ts
(readCommonFilters, buildDeclarationWhere, buildOrderBy, plus the
RoleBucket CEO/CFO/EXEC/BOARD multi-language regex map).
Caching strategy
Two cache profiles applied via Cache-Control headers:
LISTING_CACHE = public, s-maxage=60, stale-while-revalidate=300Applied to:/declarations,/signals,/recommendations,/insiders,/insiders/{slug}/declarations,/companies/{slug}/declarations.AGGREGATE_CACHE = public, s-maxage=300, stale-while-revalidate=1800Applied to:/clusters,/leaderboard/*,/sectors,/score/distribution.
Public endpoints (/health, /stats/summary, /oos-performance) keep their
existing custom cache headers.
API key gating recap
- All
/api/v1/*endpoints except/health,/stats/summary,/oos-performance,/sandbox/*require an API key (Authorization: Bearer <key>orX-Api-Key). - Tier-aware payload on
/recommendations: PRO + QUANT receive abacktestblock per pick; FREE gets the signal only. - Tier-aware response on
/export: QUANT redirects to a signed Parquet URL, PRO streams a CSV sample, FREE gets 100 sample rows. - Daily quota: 5,000 req/day in beta, enforced via
requireApiKeyand surfaced throughX-RateLimit-*headers.
OpenAPI spec changes (src/lib/openapi-spec.ts)
- 5 new paths documented with full params, examples, security tagging.
- 3 new tags:
Recommendations,Leaderboards,Sectors. /declarationsparams extended:role,maxAmount,minMcap,maxMcap./signalsparams extended:from,to,market,role,minAmount,minMcap,maxMcap,cluster,sort,order,offset./insidersparams extended:role,minDeclarations,sort,order./insiders/{slug}/declarationsparams extended: full filter set./companies/{slug}/declarationsparams extended: full filter set.- New
/clusterspath documented (was missing in spec).
Smart query examples
# Top US BUYs by CEOs or CFOs, last 30 days, score >= 60, mid-cap only
GET /api/v1/signals?market=us&role=CEO,CFO&from=2026-04-19&minScore=60&minMcap=200000000&maxMcap=5000000000
# Mode-driven recommendations (general, PRO unlocks backtest)
GET /api/v1/recommendations?mode=general&lookback=90&market=fr&limit=20
# Apple-only history for one insider since 2020
GET /api/v1/insiders/tim-cook/declarations?from=2020-01-01&companies=AAPL&direction=BUY
# Top accumulators YTD, mid-cap only
GET /api/v1/leaderboard/companies?period=ytd&metric=netBuy&minMcap=200000000&maxMcap=10000000000&limit=25
# Sector rotation 90 days, English labels
GET /api/v1/sectors?period=90d&lang=en
# Score distribution histogram for current 90d cohort
GET /api/v1/score/distribution?lookbackDays=90&bucketSize=5
Validation
npx tsc --noEmit: green on all API code (pre-existing email-template errors unrelated and present before this change).npm run lint:emdash: OK · no em-dashes in user-facing copy.npm run lint:emoji: OK · 449 files scanned.npm run build: OK · compiled in 5.3s, 2217 static pages generated.